Skip to content

About

Static recompilation of SimCity (SNES) for Windows and Linux, including Steam Deck. ROM not included.

Resources

Stars

1 star

Watchers

0 watching

Forks

 
 

Latest commit

 

History

128 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SimCity SNES Static Recomp 1.4.0

Native static recompilation core for SimCity on the Super Nintendo Entertainment System. Windows and Linux frontends are supported; the core builds on both platforms.

The original game ROM is not included. Use an externally supplied, legally obtained ROM matching ROM-REQUIREMENTS.txt.

Screenshots

The Linux frontend running the live city in Wide Screen. The extra map is real city data on both sides, and the HUD and construction toolbar sit on the native columns the guest placed them on.

The city view in Wide Screen, with the construction toolbar on the left edge

The settings overlay opens over the game frame — no second window, no font library, nothing to install but SDL2.

The F1 settings overlay

Cheats have their own submenu, because freezing money is not a display setting and burying it under mouse sensitivity made it easy to toggle by accident.

The F1 cheats submenu

These are captured from the real frontend by scripts/capture-screenshots.py, which runs it on a virtual display and drives it with synthetic input — the images are not mock-ups and cannot drift from what ships.

What fully static recompilation means

SimCity's executable W65C816 game instructions were analysed and translated into generated native C before the application was built. Production dispatch uses exact processor-state and program-counter contexts. It contains no general-purpose SNES CPU interpreter, runtime opcode decoder, dynamic recompiler, JIT, or automatic emulator fallback.

The audio program is static too. SimCity's exact S-SMP program-counter/opcode authority dispatches only compiled SPC700 instruction forms. Its protected-code bitmap rejects writes to statically owned driver code, and unknown execution or semantic ARAM reads stop with a diagnostic. The former emulator S-DSP runtime has been removed. A project-owned fixed 32-phase S-DSP implements register timing, BRR decoding, Gaussian interpolation, envelopes, noise, pitch modulation, echo/FIR and signed 16-bit stereo PCM at the native 32,040 Hz rate.

Game simulation, graphics, samples, music and effects are not prerecorded. They remain live state driven by the external ROM, cartridge memory, WRAM, VRAM, ARAM, controller input and SNES timing.

The complete runtime includes:

  • Generated exact-context W65C816 game-code dispatch.
  • Native cartridge, WRAM, bus, DMA, HDMA, controller and CPU-I/O handling.
  • Native PPU registers, scanline events, rendering and framebuffer output.
  • Exact rational NTSC scheduling and one guest frame per host deadline.
  • Fail-closed exact-PC S-SMP AOT and project-owned 32-phase S-DSP.
  • Native 32,040 Hz stereo PCM with knownness, overflow and hash diagnostics.
  • Battery SRAM and deterministic snapshots including continuing audio state.
  • A Windows launcher (Win32/GDI, SDL3 gamepad, DirectSound) and a Linux frontend (SDL2, windowed) with gamepad support, arbitrary window sizing and an optional pointer-driven guest cursor, tested on Steam Deck.
  • Windowed game-frame screenshots and exact fullscreen-presentation captures.

SimCity Wide Screen

Wide Screen is a game-specific core feature, not frontend stretching. The core can render 398x239: the original 256-pixel view plus 71 real city-map pixels on each side. It extends BG1/BG2 sampling, camera limits, the map cursor and building placement while keeping the HUD and toolbar anchored correctly. Title, setup, tutorial prompts, scenario selection and modal screens retain their native layout. The toolbar control is enabled by default, persists in settings.ini, and can be changed while a game is loaded.

Windows frontend and audio

Version 1.4.0 ports the current Jungle Strike frontend architecture while retaining and adapting SimCity's widescreen controls and dynamic geometry. Win32/GDI owns windows and presentation. SDL3 is used only for gamepad access.

The static core produces 32,040 Hz PCM from guest time. The host drains PCM during long guest frames, applies the selected nearest, linear or cubic-Hermite speaker resampler, and writes a DirectSound ring buffer. The playback design is based on the proven Mesen approach: cursor-derived latency measurement, pre-roll, bounded drift correction, recovery and exact rational frame pacing. The default speaker rate is 48,000 Hz. Extra forced latency is disabled by default and, when enabled, ranges from 0 to 40 ms. Host output changes never alter the core's native PCM authority.

Mesen was used as the hardware-behaviour and frontend-timing reference during development. Snes9x-derived S-SMP execution semantics remain under their original license and are restricted to the generated fail-closed SimCity AOT authority. Neither emulator is embedded as a runtime fallback.

Linux frontend

The Linux frontend uses SDL2 for window management, rendering and audio. It accepts the ROM path via command-line argument or the SIMCITY_ROM_PATH environment variable. It is tested on Steam Deck (SteamOS, x86_64), where it holds the native 60.0988 Hz frame cadence at 1280x800 with widescreen on.

./simcity-linux --rom /path/to/SimCity\ \(USA\).sfc

Options

Option Values Default Description
--rom <path> file required Path to SimCity (USA).sfc ROM
--resolution <N> 0-3 0 (480p) 0=480p, 1=720p, 2=800p, 3=1080p
--size <WxH> e.g. 1280x800 — Arbitrary window size; overrides --resolution
--widescreen flag off Enable 398x239 core widescreen output
--soft-mouse flag on Drive the guest d-pad cursor from the host pointer (on by default; the flag is now redundant but kept for compatibility)
--mouse-sens <N> 1-64 2 Soft-mouse threshold, texture px per frame

Settings menu

Press F1, or both stick clicks together, in game to open the settings overlay. It is drawn on top of the game frame with a built-in 5x7 bitmap font, so the frontend needs no font library and no TTF file — only SDL2. Navigate with the arrow keys or the d-pad (including on Steam Deck): Left/Right changes a value, B activates.

The menu pauses the guest: no frame advances and no audio drains while it is open. Advancing would spend money or scroll the city underneath the settings being changed.

Both the settings menu and the CHEATS submenu are full-screen overlays.

Row Effect
Resolution 480p / 720p / 800p / 1080p, applied to the live window
Widescreen Toggles the 398x239 core output
HUD shift X −142..+142 px, moves the in-game HUD and toolbar. Defaults to -71, which cancels the widened map margin and restores the HUD to its native column; 0 is the old, displaced position
Soft mouse Toggles pointer-driven cursor (on by default)
Mouse sens 1-16, lower is more sensitive
Color SWAP R/B (default) or NORMAL
Cheats Opens the submenu
Resume / Quit —

In the cheats submenu, B confirms a one-shot action or toggles the selected value row, and X (A on the pad) goes back. Both are edge-triggered, so holding B toggles once rather than flipping every frame.

The frame is presented at the largest whole-number scale that fits the window, centred, with nearest sampling, so each guest pixel stays a sharp square and the aspect ratio stays correct (398x239 is 1.67:1; stretching to a 4:3 window would distort it). Any leftover border is left as background.

Linear filtering was tried and rejected: it turned every pixel into a blur, which is the opposite of what this content wants.

Settings persist to settings.ini on exit and are read at startup. The file uses the same [General] section and key names the Windows launcher writes, so one file works on both frontends. Command-line options override the file.

HUD shift X (why it exists)

The in-game HUD — status bar, construction toolbar, message box — is drawn from OAM sprites that the guest places in native 256-pixel screen space. In the widened view the city map gains 71 px on each side, and every sprite is moved by that margin so world objects stay registered with the map. That same 71 px also moves the HUD, which is why the toolbar sits away from the edge when widescreen is on and is correctly placed when it is off.

No field in an OAM entry separates HUD chrome from world objects: index, y band, priority and palette all overlap. The guest does mark the one exception in WRAM, though — while map focus is active, OAM 0–3 are the map cursor, and everything else that is live is chrome. The renderer therefore takes the offset for every sprite except the map cursor, which keeps its own map-registered displacement.

No OAM index threshold is used to make that split. One would tear any chrome sprite straddling it, and one did: the tutorial mayor spans OAM 0..27 and was split down the middle by an earlier index-based rule.

The value is in pixels, applies only while widescreen is on, and leaves the city map itself untouched: at -71 the map region is pixel-identical, and the map cursor keeps its own displacement.

It ships defaulted to -71, which cancels the margin exactly and is what a player sees on a fresh install. headless-profile --hud-shift 0 does the same for A/B against the pre-T050 renderer.

Settings overlay (F1)

The overlay now occupies the full window area instead of only the bottom‑right corner. Navigation remains with arrow keys / d‑pad; B activates a row.

Cheats

Only cheat addresses verified against this core are offered. Funds sit at WRAM $0B9D as a 24-bit little-endian value; this was confirmed by reaching a live city and observing $004E20, the documented $20000 starting balance. Addresses used by other emulators for instant-build and disaster toggles were deliberately left out: they are unverified here and would silently do nothing.

Known issue: the money cheat (F1 → Money) does not take effect in the current build; investigation in progress.

Pointer input

--soft-mouse maps the host pointer onto the guest's own cursor by synthesising d-pad presses from per-frame pointer motion. The OS cursor is hidden while it is on, because the guest draws its own.

The pointer buttons drive the guest face buttons: left mouse is A, right mouse is B. The title has no SNES Mouse peripheral, so this is the only mouse-shaped behaviour available for confirming actions.

This is deliberately not a SNES Mouse emulation. That peripheral would have to be answered on a controller port, and the SimCity ROM never asks for one: a mouse is distinguished from a pad by reads past bit 15 ($4219/$421A/$421B), and the game reads $4218 only — two ordinary 2-byte controller reads. Driving the guest's d-pad cursor is the only mouse-shaped behaviour this title can use.

Motion is mapped by rate, not by position feedback. The core exposes cursor X ($025D, $01EB) but has no cursor Y, and guessing that address would steer the cursor diagonally into map edges. Rate mapping needs no guest state, at the cost of no self-correction: if the guest's step size differs from pointer speed the cursor lags slightly. Keyboard and gamepad d-pad always take priority, so the two input paths cannot fight over the cursor.

Keyboard controls:

Key Action
Arrow keys D-pad
Z B
X A
A L
S R
Return Start
Backspace Select
Q Y
F1 Toggle the settings menu
Escape Close the menu, or quit

On a Steam Deck both stick clicks together also toggle the settings menu, so it is reachable without a keyboard. The shortcut fires on the edge only, and it is checked before the game reads the pad, so pressing both sticks never also acts on the game.

On systems where the renderer cannot access /dev/dri/ directly (headless or unprivileged environments), force software rendering:

SDL_VIDEO_RENDERER=software ./simcity-linux --rom /path/to/rom.sfc

Linux build dependencies

Package Ubuntu/Debian Fedora Arch openSUSE
CMake >= 3.20 cmake cmake cmake cmake
GCC / Clang gcc g++ gcc gcc-c++ gcc gcc gcc-c++
SDL2 devel libsdl2-dev SDL2-devel sdl2 SDL2-devel

libsdl2-dev is required, not optional: the Linux frontend is written against the SDL2 API and has no SDL3 or Vulkan path. Without it, CMake stops at configure time and names the package to install. To build only the portable core and the headless test, skip the frontend:

cmake -S . -B build -DBUILD_LINUX_FRONTEND=OFF

A ROM matching ROM-REQUIREMENTS.txt is needed at runtime but is never distributed with the build.

Installation (one command)

curl -fsSL https://raw.githubusercontent.com/linuxkafe/SimCity-SNES-Static-Recomp/main/scripts/install-deck.sh | sh

The script:

  • downloads the pre‑built binary (verified with SHA‑256) from the GitHub release page, falls back to building from source if the download fails,
  • installs any missing build dependencies (base-devel cmake git pkgconf glibc linux-api-headers sdl2-compat) on the Deck,
  • asks for the ROM path (~/simcity-data/SimCity.sfc),
  • compiles (or uses the pre‑built binary) and creates a run.sh launcher,
  • registers a Steam shortcut (F1 opens the settings overlay; both stick clicks together also open the menu),
  • creates a desktop entry for desktop mode.

After the first run the COLOR menu item is set to SWAP R/B (the default that works on the Deck). Change it to NORMAL if your display shows the correct colours without swapping.

The binary is pre‑built and verified – it contains no ROM data (verified by scripts/verify-release.py). If you prefer to build from source, run the installer with --from-source or compile manually as shown below.

Steam Deck

The static-recomp core compiles natively on the Steam Deck (x86_64, SteamOS holo). SDL2 is pre-installed on SteamOS.

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)

Run with:

./build/frontend/linux/simcity-linux --rom /path/to/SimCity\ \(USA\).sfc --resolution 2 --widescreen

Steam Deck Gaming Mode (Recommended)

For the best experience, use the provided launcher:

# Copy ROM to data directory
mkdir -p ~/simcity-data
cp /path/to/SimCity\ \(USA\).sfc ~/simcity-data/SimCity.sfc

# Run from Gaming Mode application launcher
# "SimCity SNES Static Recomp" appears in Games category

Or via script:

~/simcity-data/run_simcity.sh

The launcher configures:

  • Resolution: 800p (1280x800) — optimal for Deck's 1280x800 display
  • Widescreen: Enabled (398x239 core output)
  • Video driver: Wayland (via gamescope)

Headless smoke test (via SSH)

SDL_VIDEODRIVER=dummy ./build/frontend/linux/simcity-linux --rom "/path/to/SimCity (USA).sfc" --resolution 0
# Gamepad connected: Steam Deck Controller

Colour order (menu setting)

The default is SWAP R/B, which is what reads correctly on the Steam Deck: the controller logo shows A red and X blue, and the in-game R/C/I are right. Set COLOR to NORMAL in the menu to get the raw core channel order instead, or use --swap-rb / --normal-colors. The choice is stored in settings.ini as ColorMode.

The frontend uploads 0xAARRGGBB through SDL_PIXELFORMAT_ARGB8888, and every automated check says that reproduces the core byte for byte on the accelerated renderer, through Wayland, and through gamescope. SWAP R/B therefore compensates for something downstream of the renderer that those captures could not show; it exchanges the red and blue byte of every pixel at upload time and leaves the rest of the pipeline untouched.

Colour check (channel order)

The frame is uploaded as SDL_PIXELFORMAT_ARGB8888, matching the core's 0xAARRGGBB output. ARGB8888 and XRGB8888 were both measured on the OpenGL renderer and both reproduce the core byte for byte; ABGR8888 transposes red and blue. If the picture looks wrong, run:

./build/frontend/linux/simcity-color-ground-truth "/path/to/SimCity (USA).sfc" exact

It re-derives the expected channel order from the SNES BGR555 hardware format rather than from the core's own output, so a swap inside the core cannot pass, then reads the frame back through the renderer and reports any pixel that differs. To capture what the renderer actually produced rather than the core's framebuffer:

./build/frontend/linux/simcity-linux --rom "/path/to/SimCity (USA).sfc" \
  --screenshot /tmp/frame.ppm

Or use the headless test binary (no window, no audio):

./build/frontend/linux/headless-test "/path/to/SimCity (USA).sfc" 300
# OK: 300 frames advanced successfully
# Current frame: 300
# Instructions: 3798805
# Master clock: 107159420

Vulkan

Not implemented. SDL2 is used on all platforms. SDL3 was evaluated and rejected for now: its 2D renderer and audio APIs differ from SDL2's, so a correct port is a real port rather than a build-flag change. SDL3 also still carries the personal-use-only Snes9x terms noted under Licensing, so adding it is a decision that should be made deliberately rather than by accident.

Known Steam Deck Issues

Issue Status Workaround
Video driver only works in Gaming Mode Expected Run from Gaming Mode, not Desktop/SSH
SDL2 only; no Vulkan path Known gap SDL3's 2D renderer differs from SDL2's API and is not implemented here
SSH/X11/Wayland fail outside gamescope Expected Use SDL_VIDEODRIVER=dummy for headless test

Deploy script

deploy-linux.sh is the single supported convenience path. It always configures Release, builds, and stages dist/linux/ with the binary and a run.sh that forwards any extra options:

./deploy-linux.sh                 # build Release, stage dist/linux/
./deploy-linux.sh --deck HOST     # additionally scp to HOST:~/simcity-build/

run.sh passes options straight through:

dist/linux/run.sh rom.sfc --size 1280x800 --widescreen --soft-mouse

Plain cmake remains the source of truth if you would rather drive the build yourself.

Prebuilt binaries, and where they belong

A prebuilt Linux binary is safe to distribute: it carries no game data. scripts/make-release.sh does not assert that, it proves it. Given the ROM, it checks that no 4 KiB slice of the ROM appears anywhere in the binary, that there are no large repetitive regions suggesting embedded data, that the binary refuses to start without a ROM, and that it rejects a correctly-sized file with the wrong contents:

ok  nenhuma das 33 fatias de 4096 bytes da ROM aparece no binario
ok  sem regioes grandes e repetitivas que sugiram dados embutidos
ok  recusa arrancar sem ROM (pede --rom)
ok  rejeita um ficheiro de tamanho certo mas conteudo errado
O binario pode ser distribuido: nao contem dados do jogo.

It writes dist/linux/simcity-linux, a .sha256, and a release.json recording "requires_rom": true and "rom_shipped": false.

These artifacts are deliberately not committed to git. build*/ and dist/ are ignored, and that is the right place for them: a 9 MB executable in history is permanent bloat that cannot be cleanly withdrawn later, it cannot be reviewed, and it goes stale against the sources it was built from. Ship binaries through make release or a GitHub Release, and let release.json carry the proof.

The ROM stays external and unmodified. That is the project's release invariant (Wide Screen - 1.4.0.txt) and this does not change it.

Performance notes (measured)

Frame budget on the Steam Deck is 16.641 ms (60.0988 Hz NTSC).

Emulation versus rendering

simcity_recomp_advance() performs the real render internally; a second call to simcity_recomp_render_current_frame() then hits the full-state frame cache and costs almost nothing. Any tool that times those two calls separately and labels them "advance" and "render" is reporting the render cost under the wrong heading. Measured directly against simcity_recomp_advance_headless(), which passes render_frame = 0:

Component Cost per frame
Emulation (advance_headless, no render) 3.57 ms
Rendering ~10.5 ms
Total ~14.1 ms

Rendering is roughly 75 % of the frame. headless-profile grew a --no-pc-profile flag so timings can be taken without the per-instruction PC histogram, which is otherwise active during every run.

Current figures (dev host, -O3 Release)

Configuration Per frame Observed
-O0 build, frame rendered twice ~105 ms ~10 fps
-O3 Release, frame rendered twice ~34 ms ~29 fps
-O3 Release, single render ~14.1 ms ~71 fps
-O3 Release, emulation only ~3.6 ms ~280 fps

Median of six runs over 950 frames. The earlier ~15.4 ms / 57.4 fps figure predates the per-pixel optimisations below.

What made the renderer faster

The background sampler runs three times per pixel, so its arithmetic dominates. Three changes, each verified bit-identical by comparing frame hashes over 950 frames:

  1. background_pixel divided by runtime values four times per pixel. The map is always 32 or 64 cells and the tile size always 8 or 16, so every divisor is a power of two and the results are provably unchanged by shifts and masks. −14.7 %.
  2. The same substitution in city_background_pixel (widescreen sampler). No measurable effect on the headless benchmark, because the widescreen city view is never reached in those 950 frames; kept because it is provably equivalent and removes four divisions per pixel from the live city view.
  3. ~15 PPU constants (mode, bpp, layer size register, map base, character base, tile size, world extents, mosaic parameters) were recomputed on every pixel although they depend only on registers latched per scanline. They are now computed once per line per layer. −9.1 %.

Render-path work is now ~10.5 ms of the ~14.1 ms frame. What remains in background_pixel is genuine VRAM tilemap and tile fetch.

Link-time optimisation was evaluated and rejected: it changed the measured time by ~0.6 %, within run-to-run noise, and cost a 4× build-time increase.

The remaining wait tail is why 60 fps is reached but not locked: SDL_Delay has roughly millisecond granularity and tends to overshoot.

Two further problems were compounding:

  1. Unoptimised build. With no CMAKE_BUILD_TYPE the core compiled at -O0. The build system now defaults CMAKE_BUILD_TYPE to Release; explicitly select it for any performance measurement.

  2. Every frame was rendered twice. simcity_recomp_advance() performs the host frame conversion itself, and the frontend then called simcity_recomp_render_current_frame() on top of it. The frontend now advances with simcity_recomp_advance_headless() and converts exactly once. The two routes were verified to produce byte-identical framebuffers over 600 frames in both display modes.

  3. Audio backlog, not underrun. The SDL device buffer was 8192 frames, which is 256 ms of slack at 32,040 Hz. SDL drains PCM in real time, so a quarter-second backlog is permanent, audible latency. The device buffer is now 512 frames (16 ms), PCM is handed over with SDL_QueueAudio, and surplus is discarded per frame to bound drift.

    Measured end-to-end queue occupancy on the Deck over 58 samples: min 16.6 ms, median 22.1 ms, max 33.3 ms, with the core-side backlog at zero throughout. That is the buffering actually in front of the speaker; the 512-frame figure is only the device buffer, not the whole latency.

Audio reaches the device with SDL_QueueAudio from the main thread. The callback form let SDL's audio thread read the core's PCM ring while the main thread was still writing it in audio_sink(), which was a data race; queueing keeps one writer and one reader on different objects without holding a lock across the whole frame.

Per-frame SHA-256 of the framebuffer is diagnostic metadata with no consumer outside the renderer, and cost ~3 ms per frame. It is now computed only while a static-core log is open.

Licensing

This repository currently ships no LICENSE file, and none can be asserted here. This section records the facts rather than granting terms.

  • The project is derived from an upstream repository (Junior-Jones/SimCity-SNES-Static-Recomp, reachable via the upstream git remote). Its terms govern what this distribution may do; they have not been verified here.
  • static-recomp/static-audio/snes9x-bapu-aot/ contains retained Snes9x SPC700 execution semantics. The bundled SNES9X-LICENSE.txt is not an OSI-approved licence. It states Snes9x is "freeware for PERSONAL USE only" and that commercial users "should seek permission of the copyright holders first".
  • Because of that embedded restriction, this combined work cannot be relicensed under a permissive licence such as MIT, BSD or Apache by the project alone, and commercial redistribution is not clearly permitted.
  • SDL3 (zlib) and the project-owned S-DSP are separable and are documented in THIRD-PARTY-NOTICES.txt.

Anyone wishing to publish or redistribute this must first resolve the Snes9x personal-use-only clause with its copyright holders, and confirm the upstream terms. That is a legal decision for the copyright holder, not a build setting.

Cheats and mods (host-side WRAM access)

simcity_recomp_write_wram() lets a frontend poke guest WRAM between frames, which is how cheats and mods are implemented. It is the write counterpart to the existing bounds-checked simcity_recomp_read_wram().

uint8_t money[3] = { 0x3F, 0x42, 0x0F };   /* 999999 */
simcity_recomp_write_wram(game, 0x0B9D, money, 3);

Contract, and the parts that are easy to get wrong:

Rule Reason
Call from the thread that calls simcity_recomp_advance() the core cannot observe a concurrent host write
Call between frames, never during one a write mid-advance is a data race
Nothing is written when the call returns 0 a rejected write must not leave WRAM half-modified
Range must lie inside the 128 KiB image offsets at or past 0x20000 are rejected

The write is visible to the next frame as if the guest had stored those bytes. Battery SRAM, S-SMP and S-DSP state are untouched, and later snapshots capture it because WRAM is part of the saved runtime image.

Do not poke PPU or camera state. The core caches widescreen cursor anchors in the instance rather than in WRAM, so writing $01BD, $0139, $01EB or $025D behind its back desynchronises that cache. Cheats should target game state such as funds at $0B9D.

static-recomp/tests/test_wram_write.c pins the bounds contract, the no-partial-write guarantee, the round trip, and that the static route survives a poke. It runs under ctest when -DSIMCITY_TEST_ROM=<rom> is configured.

Known issues

Tracked as tickets under aes/tickets/ following a four-persona adversarial review. The ones that affect a user today:

Ticket Effect
T004 On a host without system SDL2, CMake reports success and the build then fails.
T005 Audio back-pressure drops all queued PCM rather than the surplus, causing audible gaps.
T006 The settings menu cannot be opened on Steam Deck without a keyboard.
T008 Quitting discards the saved city: battery SRAM is never written on Linux.
T002 README (earlier revision) pointed at a launcher script that is not in the repository.
T007 No CI job builds the Linux frontend, which is how T004 shipped.

Fixed in the review round: the red/blue channel swap (B1), --resolution being discarded (B2), the inert FREEZE MONEY row (B3), settings.ini deleting every Windows-launcher key (B4), a frozen pointer delta steering the menu (B5), divergent MouseSens bounds (T009), and a README code fence that swallowed three sections (T010).

Verification

The source includes contract tests for controller ordering, configuration, resampling, audio defaults, project-owned DSP phase timing, linked DSP purity and real-ROM snapshot PCM continuation. Long headless routes cover neutral execution, tutorial gameplay, HUD transitions, toolbar focus, map edges, wide-cursor travel, construction, scenarios, Freeland and all four map corners. Unknown static CPU/audio states and PCM overflow remain release failures.

Third-party notices and licenses are in THIRD-PARTY-NOTICES.txt and the corresponding source directories.

About

Static recompilation of SimCity (SNES) for Windows and Linux, including Steam Deck. ROM not included.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages