Static recompilation of NeXTDoom 1.2 — id Software's Doom as it shipped
for NeXTSTEP 3.3, the platform Doom was written on — from the i386 slice of
its fat Doom.app/Doom binary to native C. Every function in the game is
lifted to C and compiled into a new program; the NeXTSTEP it expects
(libsys, the Objective-C runtime, the slice of AppKit it touches) is a host
runtime on SDL2. No emulator.
Built on the pcrecomp toolchain:
its Mach-O front end
(tools/macho) and
NeXTSTEP host runtime
(runtime/nextstep),
both on pcrecomp's main since
#25, and following its shared
house style for recompilation projects.
Generated source is not distributed. You supply your own NeXTSTEP 3.3 install; the lifter runs on your machine and writes the C into a gitignored folder.
v0.1.0 — alpha. It boots and plays the attract demo.
crt0, main, the nib, appDidInit: and D_DoomMain all run as recompiled
code: the title screen comes up and the demos play. Everything on screen below
is the game's own code, recompiled.
| Part | State |
|---|---|
| Lift | 676 functions, 0 errors, every body decodes onto the next start |
| 3D renderer, sprites, status bar, palette effects | Working (attract demos) |
R_DrawColumn / R_DrawSpan (hand-written assembly) |
Working |
| Keyboard | Wired through VGAView keyDown:/keyUp:, not play-tested |
| Mouse, sound, window scaling, netgames | Not yet (roadmap) |
Headless --record, conformance harness |
Not yet (roadmap) |
![]() |
![]() |
| Title screen | Shotgun versus imp, demo 1 |
![]() |
![]() |
| A fireball coming down the corridor | The blue-floored room |
You need a NeXTSTEP 3.3 Intel install (a disk image is fine) with
/LocalApps/Doom.app on it. Nothing else from it is used except /usr/shlib.
Prerequisites, on Windows 10 or 11:
- MSYS2 with the mingw64 toolchain, SDL2, CMake and
Ninja (tested with gcc 15.2, CMake 4.2, Ninja 1.13):
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja - Python 3.11+ with
capstone(tested with 3.13 and capstone 5.0.7):py -3 -m pip install capstone - A checkout of pcrecomp next to this
one (
../pcrecomp), or anywhere, named byPCRECOMPfor the Python scripts and-DPCRECOMP=<path>for CMake.
Commands are for a Git Bash or MSYS2 shell, from this folder:
- Copy the game out of the disk image with pcrecomp's UFS reader:
UFS=../pcrecomp/tools/macho/ufs.py MSYS_NO_PATHCONV=1 py -3 $UFS hd.img get /LocalApps/Doom.app original/Doom.app MSYS_NO_PATHCONV=1 py -3 $UFS hd.img get /usr/shlib original/shlib
- Lift:
Expected:
py -3 run_lift.py
[*] code=0x00003990-0x00022E50 entry=0x00003990 functions=676 imports=59 ============================================================ functions 676 errors 0 files 3 lines 92,838 1.3s ============================================================ - Build:
Expected:
export PATH=/c/msys64/mingw64/bin:$PATH cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER=gcc cmake --build build
build/nextdoom.exe, about 1.4 MB. - Run:
./build/nextdoom.exe. The window opens on the title screen and the attract demos start.
Usual trip-ups: py vs python (use the py launcher; the Microsoft Store
python alias is not a real interpreter), MSYS_NO_PATHCONV=1 (without it
MSYS rewrites /LocalApps/... into a Windows path), and a PATH change that
needs a new terminal.
A one-click Setup.cmd quick start is on the roadmap.
./build/nextdoom.exe runs the game from original/ (the path is baked in at
configure time). Diagnostics are environment variables:
| variable | effect |
|---|---|
NS_TRACE=1 |
log every import bound and every message sent |
NS_SHOT=first,count,path%05d.bmp |
save frames first..first+count-1 (how these screenshots were made) |
NS_SHOT=400,1,shot%05d.bmp ./build/nextdoom.exedocs/architecture.md covers the design: how the function catalog is found, how shlib imports and Objective-C methods bind to host shims, the startup path, and video.
See Step by step above. run_lift.py and CMakeLists.txt document each step.
MIT — see LICENSE. This covers the code in this repository only. Doom is © id Software and NeXTSTEP is © NeXT / Apple; no game or system code or data is included.





