DKC3Recomp
DKC3Recomp brings Donkey Kong Country 3: Dixie Kong's Double Trouble! to PC.
- Type: PC port
- Game: Donkey Kong Country 3: Dixie Kong's Double Trouble!
- Runs on macOS and Windows
- By elliotttate
- Latest release v0.0.6, 2026-09-13
- Source: https://github.com/elliotttate/DKC3Recomp
README
DKC3Recomp
A native recompilation of Donkey Kong Country 3: Dixie Kong's Double Trouble! (SNES, USA, En/Fr) built the way DKC2Recomp was built: the game's code is statically recompiled to C by snesrecomp from a bank configuration derived from a public disassembly, the shared snesrecomp runtime executes anything the analysis cannot prove through its 65816 interpreter, and project-owned hosts present the game natively on macOS and Windows.
You must supply your own DKC3 ROM. The supported image is the headerless
North American (En,Fr) release, 4 MiB, SHA-256
2277a2d8dddb01fe5cb0ae9a0fa225d42b3a11adccaeafa18e3c339b3794a32b. No ROM
data, generated code, or extracted assets are stored in this repository.
Status
Bring-up. See docs/BRINGUP.md for the dated record of
what runs and what has been verified, and
docs/WIDESCREEN_GUIDE.md for how the widened
presentation works and how its defects are diagnosed and fixed. Levels present
wide at 16:10, 16:9, and the selectable 21:9 ultrawide mode with DKC2Recomp's
terrain reconstruction driven by DKC3's own level map, verified on Lakeside
Limbo.
The 21:9 option uses the nearest symmetric width that preserves the shared
runtime's safe sprite coordinate range: 446x224, or approximately 20.91:9.
Screens the map does not cover center the native frame between black margins.
The placed-object spatial scan and final activation checks, the sprite renderer
culls, and the static banana arcs are widened to the presented view by
scripts/apply_dkc3_widescreen_overrides.py, verified on Lakeside Limbo. The
scan includes adjacent 256-pixel cells so 21:9 objects, including objects in
quick saves made by older builds, do not wait for a cell boundary to activate.
Murky Mill's HDMA-windowed BG3 light cones are evaluated across the physical
widescreen span instead of being clipped and repeated at the native edges,
verified at the reported quick-save state in both 16:10 and 16:9.
Floodlit Fish's underwater BG3 color-math composition now receives its
subscreen tint across transparent side-margin pixels without clipping the
reconstructed BG1 terrain at the native edges, verified at the reported
quick-save state in 16:10, 16:9, and 21:9 with an unchanged 4:3 frame.
KAOS's body layer, enabled partway down the frame by HDMA, now uses its
complete object tilemap in the wide margins. This fixes the right-edge body
cutoff and the repeated fragment at the left edge in the reported boss save.
The streamed waterfall layer now decodes its authored columns into the wide
margins, checked against the native tilemap every frame. Waterfalls keep their
world positions after scrolling instead of disappearing at one edge and
repeating at the other, verified at the reported save in all wide aspects.
Bleak's snowball arena now preserves Mode 2's correct background/sprite order,
so the snowman appears in front of the distant snowbank and behind foreground
cover. Its bounded background maps fill 16:10, 16:9, and 21:9 using their
hardware wrap, with the native center and gameplay unchanged by widening.
Pothole Panic's cave now fills the wide view from its authored level map.
Its shape-1 layout uses 32 metatile rows per column, twice the height of
the previously supported horizontal layout.
A second layer that streams a strip of the level map, Riverside Race's reflection under the water line, is served in the margins from the terrain store at the row offset its rows prove every frame, while its static underwater backdrop wraps as a plane judged by row-level write tracking; and the first visible row of the margins now decodes like the rest instead of being blanked on tile boundaries. See docs/BRINGUP.md for the evidence.
Native macOS release
The v0.0.6 release fixes the Windows menu bar staying on screen in fullscreen, restores the requested window size under the menu bar, keeps the game DPI-aware when the launcher is skipped, and makes the Windows CMake configure work again; it carries the unchanged v0.0.4 Mac archive below. The Mac source, menus, and display-link pacing are retained; the Mac binary has not been rebuilt for these Windows-focused releases.
Download DKC3Recomp-v0.0.4-macOS-arm64.zip from
Releases, extract it, and open DKC3Recomp.app. Select your
own legally obtained North American (En,Fr) ROM in the launcher; the ROM stays
at its original path and is never copied into the application bundle.
The published v0.0.4 bundle includes the Floodlit Fish tint fix, the river's second-layer reflection and backdrop in the margins, and the fix for the strip that flashed at the top of the margins; v0.0.3 carried 21:9 and the adjacent-cell placement activation fix.
This release is for Apple silicon running macOS 26 or newer. The app is ad-hoc signed rather than notarized, so if Gatekeeper blocks the first launch, Control-click the app in Finder, choose Open, and confirm once. The project is still in bring-up: the tested boot, launcher, save-state, and Lakeside Limbo paths work, but full-game compatibility is not yet claimed.
Building on Windows
The Windows x64 SDL build has passed all 23 project tests, a 4,801-frame headless run, and a packaged launcher/visible-game smoke check. Full-game completion and hardware/controller coverage are not claimed.
Requirements: Visual Studio 2022 with Desktop development with C++, CMake, and Python 3. Initialize the Git submodules before building. In PowerShell:
python scripts/generate_snesrecomp.py --analysis-backend python --rom 'C:\private\dkc3.sfc'
cmake -S . -B build-windows -G 'Visual Studio 17 2022' -A x64 `
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DSNESRECOMP_SDL_BACKEND=SDL2 `
-DDKC3_ROM='C:\private\dkc3.sfc'
cmake --build build-windows --config Release --parallel 4
ctest --test-dir build-windows -C Release --output-on-failure
Run build-windows/Release/DKC3RecompSDL.exe. This is the shared SDL2/OpenGL
host with 4:3, 16:10, 16:9, and 21:9 presentation, reconstruction upscaling,
overlay, and audio rate control. Keep SDL2.dll and the assets directory
beside the executable when moving it. Select your own ROM in the launcher.
The separate DKC3Recomp.exe in the build directory is the legacy Win32 host;
portable packages use the SDL executable renamed to DKC3Recomp.exe.
The game window now has native Game and View dropdown menus matching
the Mac's game commands: Pause / Settings, Quick Save, Quick Load, fullscreen,
nearest/bilinear scaling, and all four aspect ratios. Windows also exposes
reconstruction scaling, all five dither/edge-reconstruction levels, level-edge
policies, and screen models in View submenus. Selections apply live and are
remembered beside the executable. Game > Pause / Settings > Settings opens
the same detailed sliders and dropdowns as the Mac overlay, including
reconstruction strength, softness, shading, audio, and volume; Controls and
Assist Tools are adjacent tabs. These menus appear after launching the game,
not on the pre-boot ROM picker. Ordinary Windows minimize/close commands replace
the macOS-specific Hide and application-management commands.
The Windows title bar, menu bar, and nested dropdowns use a dark theme.
The product title is simply DKC3Recomp, without a pre-release label.
CMake fetches the pinned SDL 2.30.9 source when no SDL2 package is installed.
The Python analysis backend avoids a Rust toolchain requirement. If cmake
is not on PATH, use its full path from Visual Studio's bundled CMake tools.
Private Windows smoke tests cover all four aspect modes with reconstruction,
overlay, rewind, fast-forward, and quick-state save/load. ROM-free tests remain
available with -DDKC3_BUILD_SNESRECOMP=OFF.
Building on macOS
Requirements: CMake, Ninja, SDL2 (brew install cmake ninja sdl2), Python 3,
and Rust's cargo for the native analyzer (Python falls back when it is
absent).
git clone --recurse-submodules https://github.com/elliotttate/DKC3Recomp.git
cd DKC3Recomp
python3 scripts/generate_snesrecomp.py --rom /private/path/dkc3.sfc
./build_macos.sh /private/path/dkc3.sfc
generate_snesrecomp.py verifies the ROM's hash, refreshes recomp/funcs.h,
and emits the private recompiled units under generated/ (ignored by Git).
build_macos.sh builds build/macos/DKC3Recomp.app and the headless
runner, bundles SDL2, embeds the project icon, and ad-hoc signs the app. Open
the app and select the ROM in its launcher.
Release builds enable interprocedural optimization when CMake's compiler
and linker check succeeds, allowing optimization across the generated game
code and runtime. Set -DDKC3_ENABLE_IPO=OFF when configuring to disable it;
unsupported toolchains retain ordinary Release optimization. The
project's runtime adaptations live as literal hunks under
cmake/runtime-patches/; scripts/apply_dkc3_runtime_patches.py applies
them to build-directory copies of the pinned snesrecomp sources at
configure time and fails closed when an anchor moves
(-DDKC3_RUNTIME_PATCH_DIR points a scratch build at another hunk
directory, for example with tools/diagnostics/ added). They keep the
scalar PPU's widescreen merge and composite off per-pixel branch chains,
give the shared bus a direct path for plain cartridge ROM reads, stop the
interpreter prefetching poll bytes it never consults, let the interpreter
hand a compiled routine it reaches by jump to the compiled code whenever it
owns the return frame that routine will pop (SNESRECOMP_LLE_JUMP_BOUNCE=0
restores the call-only behavior), re-interpret a compiled jump-table
dispatch whose static table misses the live index instead of skipping the
handler, and compile out audio reference diagnostics that a zero-valued
trace define had left running on every sample. Tier-2 coverage journals are now opt in
(SNESRECOMP_TIER2_CAPTURE=1), as is the stack-balance auditor
(SNESRECOMP_STACKBAL_AUDIT=1). Measurements and validation limits are
recorded in docs/BRINGUP.md.
On macOS a visible game window presents through a Metal layer driven by
CAMetalDisplayLink on its own thread (runner/macos_metal_presenter.m):
the emulation thread hands each frame to a mailbox and never enters the
window system, which removes the WindowServer round trip inside the legacy
OpenGL swap from the frame loop. The display link's callbacks also supply
the pacing ticks, so frames stay locked to the refresh as before. The
OpenGL path remains for the settings overlay, for hidden test windows and
their drawable captures, and when DKC3_METAL_PRESENTER=0 is set.
The bank configurations carry exit-width contracts (exit_mx_at) and
function splits that let the recompiler compile routines whose exits it
cannot derive; they are tables in tools/ingest_dkc3_disasm.py
(EXIT_MX_AT, FUNC_SPLITS) with the disassembly structure that
justifies each, so a re-ingest reproduces them.
The SDL host gives the active player's game controller a short haptic pulse
when a descending jump both defeats an enemy and rebounds upward. The trigger
observes the enemy's actual defeated-sprite transition, so ordinary jumps,
damage, swimming, and enemies defeated by unrelated causes do not activate
it. The rumble request runs off the frame-critical thread. The pause menu's
Settings tab shows the detected controller and rumble capability, provides a
test pulse, enables or disables the feedback, and remembers that choice;
setting DKC3_HAPTICS=0 when launching the app also disables it.
On macOS, optional MSU-1 replacement music can be enabled from Music >
Choose MSU-1 Music Pack…. Choose PCM Folder for an extracted pack or
.msu1 Archive for an archive, select it, then restart the app. The host
accepts track-N.pcm,
dkc3_msu-N.pcm, and dkc3_msu1-N.pcm naming, mixes the 44.1 kHz music with
the game's original sound effects, and preserves the selected pack for later
launches. Music > Disable Replacement Music restores the stock soundtrack
after a restart. For development runs, DKC3_MSU1_PACK=/path/to/pack selects
a pack, DKC3_MSU1_DISABLE=1 suppresses a saved selection, and
DKC3_MSU1_GAIN=0.0..4.0 adjusts replacement-music gain.
Quick loads and rewind keep the current music choice: older saves cannot
bring the original soundtrack back underneath a replacement pack. Disabling
replacement music also restores native sequencing when loading an MSU-era save.
For macOS audio isolation checks, the headless runner accepts an explicit
DKC3_MSU1_PACK too (it never reads the app's saved pack preference). Combine
it with DKC3_MSU1_GAIN=0, DKC3_SAVESTATE_INPUT, and DKC3_AUDIO_PCM to
capture only the remaining stock sound effects; omit the gain override to
capture the full replacement mix.
Headless validation
build-headless/dkc3_snesrecomp_headless /private/path/dkc3.sfc 600
runs the game for 600 frames with no window and prints frame, WRAM, VRAM,
CGRAM, and OAM hashes with video and audio activity counts. The switches
in runner/headless_main.c write frames as PPM (DKC3_FRAME_PPM,
DKC3_FRAME_PPM_PREFIX with START/END/STEP), raw audio
(DKC3_AUDIO_PCM), and memory dumps, restore an SRAM image or a quick
save (DKC3_SRAM_INPUT, DKC3_SAVESTATE_INPUT), and replay scripted
input (SNESRECOMP_INPUT_PLAY).
DKC3_PPU_LEGACY=1 selects the independent scalar renderer for pixel-oracle
comparisons. CMake applies the checked Mode 2 priority adaptation, with the
other runtime hunks, to build copies of the pinned sources; the submodule
stays unchanged.
Regenerating the bank configuration
The cfg files under recomp/ were derived from the
H4v0c21 DKC3 disassembly
by tools/ingest_dkc3_disasm.py, which needs a checkout of that project
with its assembled dkc3.sym beside the bank sources:
python3 tools/ingest_dkc3_disasm.py --disasm /path/to/DKC3-Disassembly --output recomp
The output holds only names, addresses, bounded ranges, data regions, and finite dispatch contracts. The disassembly itself is GPL-3 and is not redistributed here; see THIRD_PARTY_NOTICES.md.
Tests
cmake -S . -B build-headless -G Ninja -DDKC3_ROM=/private/path/dkc3.sfc
cmake --build build-headless
ctest --test-dir build-headless --output-on-failure
The unit tests cover the host modules carried over from DKC2Recomp, the
ingester, and the pacing-log tool. With DKC3_ROM set, the suite also
boots the game headlessly and, on macOS, runs the app hidden.
Lineage
The host code, build scripts, and working rules come from DKC2Recomp; the game adapter and the ingester are new. Widescreen, save tools, and the diagnostics that DKC2Recomp accumulated are not carried over until DKC3 has its own evidence for them.