Static recompilation of SimCity 2000 (Maxis, Windows 95 edition, SIMCITY.EXE
built 1996-03-07) from its shipping binary to native C. Every function in the
game — the simulation, the isometric renderer, and the statically linked MFC
and C runtime — is lifted to C and compiled into a new Windows program. No
emulator.
Built on the pcrecomp toolchain and following its shared house style for recompilation projects.
Generated source is not distributed. You supply your own copy of the game; the lifter runs on your machine and writes the C into a gitignored folder.
v0.4.0 — alpha. It plays: build a city, save it, load it, watch it animate. Windows, and Linux under Wine.
The recompiled program generates maps, takes building tools (power plants,
zones, roads), saves and loads cities through the game's own File dialogs,
and animates its palette on a 32-bit desktop. Checked against the original:
the same saved city, run for the same time in the original SIMCITY.EXE and
in the recompiled one, ends with the same funds to the dollar, and a city saved
by the recompiled game loads in the original. Everything on screen below is
the game's own code, recompiled.
| Area | State |
|---|---|
| Lift | 9,870 functions from pcrecomp's own catalog (7,045 from IDA's), 0 lift errors |
| Startup, MFC, dialogs, menus, toolbar | Working |
| Terrain generation, map rendering | Working |
| Building: power plants, power lines, zones, roads | Working |
| Simulation | Matches the original: same save, same funds after the same run |
| Save City As, Load City (File dialogs) | Working, with a compatibility fix the original also needs |
| Loading a city from the command line | Working |
| Palette animation (traffic, lights) | Working: the host emulates a 256-colour palette display |
| Intro movie | Skipped — the game looks for the CD, and says so |
| Sound and music | Working in play (not checked by the headless runs) |
| Frontend window: filters, glow, CRT, menu bar, cheats, speed slider | Working (the default; --classic for the game's own windows) |
| Save slots, mods (built-in and DLL) | Working |
| Speed | The game's own speeds, plus a slider; African Swallow is paced (below) |
Needs pcrecomp#23 (the function catalog without IDA) until it merges; build
against its branch via PCRECOMP (below).
The game runs as it shipped. Everything here is optional and sits around it:
the host draws the game's frame in its own window and adds a menu bar next to
the game's own menus. --classic turns all of it off and shows the game's
original windows.
| Menu | What it does |
|---|---|
| Graphics | Filters: nearest (original pixels), smooth, sharp bilinear, Scale2x. Integer scaling. Glow on bright, saturated pixels (lights, fire), with strength and threshold. A CRT look: curvature, scanlines, shadow mask, vignette. |
| Effects | Day and night, seasons and weather, drawn by recolouring the game's own 256-colour palette, the way 1996 hardware would have. Driven by the game's calendar and its weather. Adjustable cycle length and night depth. See docs/effects.md. |
| Play | A speed slider, 5% to 800% on top of the game's own speed setting. African Swallow is paced at twice Cheetah: the original runs it flat out, and on a modern PC a new city's whole first year went by in a fifth of a second. Also: mouse wheel zooms, and autosave every 5, 10 or 30 minutes. |
| Saves | Numbered save slots, save and load in one click. The game's File dialog is answered for you. |
| Mods | Built-in mods (Always sunny) and mod DLLs from mods\, with a small C API. mods/stipend is the worked example. See docs/mods.md. |
| Cheats | Add $10,000, $100,000 or $1,000,000, or hold funds where they are. |
| Debug | A city stats window (date, weather, funds, time of day) and frame timings. |
| Display | Fullscreen (F11), vsync. |
Settings are remembered in build\sc2k.ini. Dialogs work in the frontend
window: scroll bars, the mouse wheel and the arrow keys included. More in
docs/frontend.md.
For development and testing:
--headlessruns the game where nothing reaches your screens (works over RDP), and--recordfilms it to MP4.--inputplays scripted mouse and keyboard input.--nativeruns the originalSIMCITY.EXEunder the same recorder and script, as the reference to compare against.- Tracing via environment variables (Usage, below).
You need the Windows 95 version of SimCity 2000: the CD Collection or
Special Edition disc, which has a WIN95\SC2K folder with SIMCITY.EXE in it.
(The DOS and Windows 3.1 versions are different programs and are not supported.)
- The installer: download it from the
releases (Windows or
Linux), choose your disc, its
.iso, or a folder with the Win95SIMCITY.EXE, and press Build. It is recomp-launcher withlauncher/launcher.json, and it runs the scripts below. - Windows: double-click
Setup.cmd. It installs what is missing (Python, LLVM, the Visual Studio Build Tools), copies the game intogame\, lifts and builds, and leavesSimCity 2000 (recomp).cmdto play. - Linux:
./setup.sh. The same steps, but the Windowssc2k.exeis cross-compiled with clang-cl (build.sh, against the MSVC runtime and SDK that xwin downloads) and played under Wine withSimCity 2000 (recomp).sh. It needs clang, lld, llvm, cmake, ninja and wine (32-bit) from your package manager, and says which are missing. Under Wine the game plays in its own windows (--classic): the frontend's extras (filters, effects, the speed slider, save slots, mods) are Windows-only for now. There is no native Linux host yet.
A rerun skips the steps that are done; -Force / --force redoes them.
Prerequisites, all on Windows 10 or 11:
- Visual Studio 2022 or Build Tools 2022, with the x86 C++ libraries
- LLVM 17 or newer (for
clang-cl), CMake 3.20+, Ninja - Python 3.11+ with
capstoneandpefile(py -3 -m pip install capstone pefile) - ffmpeg on
PATH, only for--record - A checkout of pcrecomp, either next
to this one (
..\tools) or anywhere, named by thePCRECOMPenvironment variable (bothrun_lift.pyandtools\build.cmdread it)
No commercial tools: the function catalog comes from pcrecomp's disasm32.
IDA Pro is optional (see below). Until pcrecomp#23 merges, check out its
branch (feat/disasm32-lift-without-ida); main's disasm32 makes a catalog
the game stalls on.
- Copy the disc's
WIN95\SC2Kfolder intogame\, so thatgame\SIMCITY.EXEexists. - Lift:
The first run writes the function catalog,
py -3 run_lift.pyanalysis\d32_funcs.json, withdisasm32(a few minutes; delete the file to make it again). Expected:functions 9870 errors 0 files 25. - Build:
tools\build.cmd. Expected:build\sc2k.exe, about 15 MB. - Run:
build\sc2k.exe game\SIMCITY.EXE. The first line is[host] ...\SIMCITY.EXE mapped at 0x00400000, 9870 lifted functions, 0 unresolved imports.
With IDA Pro 9.x (idalib) the catalog can come from IDA instead, and the lift is about half the size (7,045 functions, a 7 MB exe):
copy game\SIMCITY.EXE work\ida_SIMCITY.EXE
py -3.11 ..\tools\tools\ida\ida_funcs.py work\ida_SIMCITY.EXE analysis\ida_funcs.json
py -3.11 ..\tools\tools\ida\ida_export.py work\ida_SIMCITY.EXE analysis\ida_codemap.json --key va
py -3 run_lift.py --catalog analysis\ida_funcs.json
Usual trip-ups: py vs python (use the py launcher; the Microsoft Store
python alias is not a real interpreter), and a PATH change that needs a new
terminal. tools\build.cmd sets up the Visual Studio environment itself.
build\sc2k.exe [--headless] [--record out.mp4] [--fps N] [--seconds N]
[--input SCRIPT] [--native] [path\to\SIMCITY.EXE] [game arguments...]
--headlessruns the game on a private desktop: it runs and paints, but nothing appears on your screen. Works over RDP. The game's frame is a fixed 1600×960 there, so scripted coordinates do not depend on your resolution.--record out.mp4films every window of the game through ffmpeg.--seconds Nexits after N seconds.- Anything after the game's path goes to the game; a city file opens that
city:
build\sc2k.exe game\SIMCITY.EXE CITIES\NYC.SC2. - The game plays in the host's own window by default, with the menus in
What's added on top.
--classicshows the game's own windows instead. - Mods: built-in and DLL mods with a small C API (docs/mods.md);
SC2K_MODS="Always sunny,City stipend"switches them on without the menu. --nativeruns the originalSIMCITY.EXEinstead, on the same desktop with the same recorder and script: the reference to compare against.--input SCRIPTplays scripted input,T:verb argsseparated by;, with T in seconds:click X,Y,press X,Y,MS(hold, for a tool's variants menu),drag X1,Y1,X2,Y2(zones, roads),key VK,type TEXT,command ID(a menu item, e.g.0x8026Save City As,0x8021Load City), andwait TITLE(until a window with that title shows; later steps count from then).
Save the current city as TESTCITY, headless:
build\sc2k.exe --headless --seconds 60 ^
--input "35:command 0x8026; 36:wait Save As; 38:type TESTCITY; 40:key 13" ^
game\SIMCITY.EXE game\DEFAULT.SC2
Diagnostics, as environment variables: SC2K_APITRACE=1 logs every Win32 call
by name; SC2K_CBTRACE=1 every call from Windows into the game;
SC2K_WATCH=1 prints where the guest is once a second; SC2K_REGTRACE=1 logs
registry access; SC2K_CAPTRACE=1 lists the game's windows during a recording.
Settings live where the game always kept them, under
HKEY_CURRENT_USER\Software\Maxis\SimCity 2000. On first run the host fills in
what the installer would have written, without overwriting anything present.
docs/architecture.md covers the design: the game image is mapped at its original address, its imports are bound to the real Win32 API, and callbacks from Windows into the game are caught with a DEP trap. docs/bringup-notes.md has the problems that took the longest to find, and docs/effects.md the optional effects, and docs/frontend.md the frontend window.
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. SimCity 2000 is © Maxis / Electronic Arts; no game code or data is included.








