Donkey Kong Country 2: Diddy's Kong Quest · DKC2Recomp
Donkey Kong Country 2: Diddy's Kong Quest
OrigenSuper Nintendo
TecnologíaRecompilación Estática (C/C++ nativo)
Disponible paraWindows, Linux, macOS
Ver proyecto oficialSobre el proyecto
Donkey Kong Country 2: Diddy's Kong Quest es un videojuego de plataformas desarrollado por Rare y publicado por Nintendo en noviembre de 1995 en Norteamérica y Japón, y en diciembre en Europa. Es la segunda entrega de la serie Donkey Kong Country y la secuela directa del juego homónimo. La trama se centra en Diddy Kong y su prometida Dixie Kong, que intentan rescatar a Donkey tras ser capturado por King K. Rool. La acción se desarrolla en la Isla Cocodrilo, compuesta por ocho mundos variados con un total de cincuenta y dos niveles.
Información oficial del proyecto
DKC2Recomp
This recompilation is a byproduct of developing snesrecomp: the games are the proving ground, while the reusable framework is the larger goal. This is a community recompilation, not an official port. Please report any reproducible gameplay, video, or audio regressions.
Static recompilation of Donkey Kong Country 2: Diddy's Kong Quest for SNES
into native desktop applications, using the snesrecomp framework. Windows
and Apple-silicon macOS builds are available. The native Mac application
includes an AppKit menu, Dock icon, platform user-data directory, and
Mac-specific exact-rate frame pacing. It is ad-hoc signed; notarization remains
open.
The 65816 game program is translated to native C where analysis can prove an exact entry state. The current profile emits 3,475 exact AOT variants and keeps two deliberate original-game fault variants on the shared 65816 interpreter. That interpreter remains available as a correctness and exceptional-path fallback. SNES hardware outside the main CPU—the PPU, SPC700/S-DSP, DMA/HDMA, controllers, and cartridge mapping—is modeled by the shared runtime.
Optional Donkey and Kiddy characters
Open the in-game pause menu with Escape, then choose Characters. Each original character slot can use Donkey Kong or Kiddy Kong; Donkey + Kiddy selects both, and Original pair restores Diddy and Dixie. The game remembers your choices between runs. Animal riders use mount-specific seated/hanging poses and attachment points. Hold Down + Y on the ground for Donkey's hand slap or Kiddy's body slam. Barrel carrying and throwing use each character's original style and timing. Neither replacement inherits Dixie's helicopter flight. Select plays a paired tag handoff when swapping Kongs. Donkey/Kiddy team pickup and throws use synchronized poses and shoulder/hand placement (private pack v5). Kiddy uses a seated recovery after a missed throw; regenerate earlier packs if he repeatedly snaps between hurt poses while waiting for the leader. Other movement/collision still uses DKC2's engine; this is not a complete DKC1/DKC3 mechanics transplant. Replacement animations freeze during Start or Escape pause. Re-import older packs for these changes.
Create the private character pack from your own Project Kongs checkout using the import instructions, then select Load character pack.... Game art is never included in this source tree or the app bundle.
Quick start
Windows release
- Download
DKC2Recomp-v0.0.8-Windows-x64.zipfrom Releases and extract the complete archive. - Run
DKC2Recomp.exe. - In the Dear ImGui launcher, select your own legally obtained North American v1.0 ROM and choose Play.
DKC2RecompSDL.exe is the alternate SDL host. Keep the bundled DLLs and
assets directory beside both executables. The archive also includes the
character importer and MSU-1 setup guides; supply those packs separately.
The selected external path is remembered in rom.cfg beside the executable.
The ROM is never copied into the release. Saves are written to
saves/save.srm, with the previous clean save retained as save.srm.bak.
Windows menus and controls
Both Windows hosts include a dark Game / View / Input dropdown bar.
Use Game for pause/resume and Quick Save/Load, View for aspect, scaling,
level edges, screen filters and fullscreen, and Input to choose each player's
Keyboard/Gamepad source or TEAM co-op policy. Changes apply while playing
and persist in launcher.cfg. Alt+Enter toggles fullscreen; Escape
leaves fullscreen when the overlay is closed, otherwise pauses/resumes.
The bar returns on leaving fullscreen.
Default keyboard: arrows move; Z jumps (SNES B), A runs/rolls (Y), X is A, S is X, Q/W are L/R, Enter is Start and right Shift is Select. Player 1 defaults to keyboard, Player 2 to the first connected gamepad; select Gamepad for both players to assign two connected pads in order. Start+Back opens/closes the pause overlay without sending the chord to the game. Bindings and deadzones are editable in the launcher or in-game overlay. GDI supports both the native menus and the full ImGui pause/settings overlay; Reconstruct is available in SDL and native Windows OpenGL. GDI exposes its supported Nearest/Bilinear samplers. The menus reflect compiled shader capability.
CRT television, characters and MSU-1 music
Open Escape > Settings > Display > CRT television. Choose Living room, Studio monitor, Soft or Custom; adjust Scanlines, Sharpness, Phosphor mask, Mask strength, Glow, Halation and Curvature. Phosphor colors are separate. Native Windows OpenGL and SDL use identical CRT passes. Tube mode supplies its own scaling; Flat panel retains Reconstruct. GDI uses flat display.
The Characters tab offers Original, Donkey Kong and Kiddy Kong for each
slot, Donkey + Kiddy, and Original pair. Load an external character pack
as described in Project Kongs. Choices and pack paths
persist in kongs.cfg. Original slot collision sizes and some movement rules
remain; this is not a full DKC1/DKC3 move-set transplant.
Under Settings > Audio, choose an extracted MSU-1 music folder, enable
Replacement music (MSU-1) and adjust Music volume. Standard
dkc2_msu1-N.pcm tracks replace music while original sound effects remain.
Missing tracks fall back to SNES music. The external folder preference is saved
in msu1.cfg. No patched ROM or .msu marker is needed. See
MSU-1 audio for state/rewind behavior and validation.
Unlocking every level in a save
scripts/dkc2_unlock_levels.py marks every real level of a save file as
cleared, which opens every path on the world maps and every world whose
boss it clears, and can open the Lost World and grant coins:
python3 scripts/dkc2_unlock_levels.py --save "$HOME/Library/Application Support/Flat2VR/DKC2Recomp/saves/save.srm" --rom /private/path/dkc2.sfc --file all --lost-world --kremkoins 75 --banana-coins 99 --snapshot "$HOME/Library/Application Support/Flat2VR/DKC2Recomp/saves/dkc2s0.sav"
It backs each file up beside itself first (.before-unlock, numbered
when one exists). Quit the app before running it, since the app writes
its own copy of the SRAM back on exit, and start from the file select
afterwards. --lost-world marks every Klubba kiosk as paid, so Klubba
lets the Kongs through without a toll, and records the five Lost World
levels as beaten, which opens Krocodile Kore. --kremkoins sets the
Kremkoin count the kiosks charge (15 each; the game holds 75). Banana
Coins are not stored in the save file, the game zeroes them whenever it
loads a file, so --banana-coins sets them only in the quick save named
by --snapshot. The percentage is recounted by the game at its next
save. --no-levels leaves the cleared flags alone, and --repair
recomputes the header of a file the game shows as empty because its sums
disagree while its data is intact.
Native macOS release
- Download
DKC2Recomp-v0.0.6-macOS-arm64.zipfrom Releases and extract it. - Open
DKC2Recomp.appand select your own legally obtained North American v1.0 ROM. The ROM remains outside the application bundle.
The v0.0.6 Mac archive is an ad-hoc-signed Apple-silicon build and is not notarized. It adds the CRT television display, the Retina pause-menu fix, and the optional Donkey/Kiddy character slots. The v0.0.8 release carries this Mac archive unchanged alongside the new Windows build; the Mac binary does not contain the new simultaneous co-op or MSU-1 support. If Gatekeeper quarantines the downloaded archive, open the app from Finder with Control-click > Open and confirm once.
Native macOS source build
Install Xcode Command Line Tools, CMake, Ninja, Python 3, Rust/Cargo, and SDL2, then run:
./build_macos.sh "/private/path/to/DKC2-USA-v1.0.sfc"
open build/macos/DKC2Recomp.app
The resulting application is build/macos/DKC2Recomp.app. It bundles its SDL2
dynamic library, carries the project icon, is ad-hoc signed, and stores ROM
selection, launcher settings, SRAM, save states, and diagnostics under
~/Library/Application Support/Flat2VR/DKC2Recomp. The private ROM remains at
its original path and is never copied into the application bundle.
Supported ROM
The launcher and runtime verify the ROM after removing an optional 512-byte copier header.
| Property | Expected value |
|---|---|
| Size | 4,194,304 bytes (headerless body) |
| CRC32 | 006364DB |
| SHA-256 | 35421a9af9dd011b40b91f792192af9f99c93201d8d394026bdfb42cbf2d8633 |
| Internal name | DIDDY'S KONG QUEST |
| Region/version | North America v1.0 |
You must supply your own lawfully obtained dump. ROMs, extracted in-game
graphics, music, level data, save files, and generated ROM-derived C are not
distributed in this repository or its release archives. The launcher includes
North American retail cover art solely to identify the supported game and
region; its source and copyright notice are documented in
recomp/launcher/README.md.
Semantic symbols for development
Reverse-engineering knowledge is kept outside the generated C.
recomp/symbols.toml assigns reviewed names, aliases, confidence, provenance,
tags, and notes to stable USA v1.0 CFG addresses. recomp/layouts.toml records
confirmed WRAM objects and fields. docs/SYMBOL_DATABASE.md is the generated
readable index.
After editing either TOML file, validate and regenerate with Python 3.11+ (or
Python 3.9/3.10 with tomli):
python scripts\build_dkc2_symbol_database.py --apply-cfg
python scripts\build_dkc2_symbol_database.py --check
python scripts\lookup_dkc2_symbol.py banana
The build tool imports all 3,314 structural CFG entries into an ignored JSON
index at .cache/dkc2-symbols.json, updates only exact-address CFG names, and
generates the constants consumed by widescreen diagnostics. Generated game C
remains ignored and must still be rebuilt from the user's verified ROM.
Widescreen route auditing
The experimental 16:9 path includes an automatic deterministic route auditor,
not only single-frame screenshots. scripts/audit_widescreen_route.py replays
composite/BG/OBJ layers and correlates them with camera state, exact
world-keyed terrain entries, margin-source provenance, and placed-object
lifetimes. Its HTML/JSON report flags raw rolling-VRAM fallback, missing
terrain replaced by transparent tiles, terrain identity changes, old-edge
seams, object spawn/despawn near the former 4:3 boundary, and active margin
objects with no OBJ pixels.
The trace also proves, for each sampled frame, how many expanded-margin cells
were requested, present, and equal to the static level source. A newer
cartridge tilemap write is treated as authoritative rather than compared with
a later animation phase. Verified transparent fallback is retained in a
separate safe-observation section; it is not counted as an actionable defect.
Object lifetime conclusions require --step 1.
Start with a coarse --step 4 route, then rerun a short suspicious interval at
--step 1. All generated evidence belongs under ignored .cache/ or an
external private test directory. See
docs/WIDESCREEN_DIAGNOSTICS.md for commands,
confidence meanings, storage costs, and limitations.
Default controls
| Action | Keyboard | Controller |
|---|---|---|
| D-Pad | Arrow keys | D-Pad |
| A / B | X / Z | B / A |
| X / Y | S / A | Y / X |
| L / R | Q / W | Left / right shoulder |
| Start / Select | Enter / Right Shift | Start / Back |
| Rewind | Hold 1 | Left trigger |
| Fast-forward | Hold 2 | Right trigger |
| Save state (selected slot) | F5 | Unbound |
| Load state (selected slot) | F9 | Unbound |
| Toggle performance log | F | — |
| Open/close overlay | Escape | Guide or Start+Back |
Each player's Configure page in the pre-boot launcher and the in-game
Controls tab edit the real keyboard and standard-controller mapping
consumed by both playable hosts.
Rewind and Fast-forward also appear there as global Assist shortcuts. The
top-level Assist Tools page edits Rewind, Fast-forward, Save State, and
Load State keyboard/controller bindings. Press a binding chip and then the
desired key, controller button, or controller axis. All mappings persist in
launcher.cfg; per-player and Assist reset buttons restore the defaults above.
The launcher exposes independent Player 1 and Player 2 source selectors. By
default the keyboard controls Player 1 and the first connected gamepad controls
Player 2. The accepted Windows host uses XInput; the portable host uses SDL
GameController. Players set to Gamepad receive connected devices in player
order, so two gamepads drive the two SNES controller ports independently.
Source, deadzone, and binding choices persist in launcher.cfg.
Two-player co-op
Selecting "2 PLAYER TEAM" in the game's own menu used to alternate control:
one Kong was player-controlled while the other followed by AI, and control
passed only when a Kong was hit or swapped. The port now makes TEAM mode
simultaneous by default: controller 1 always drives the first Kong slot and
controller 2 always drives the second, so both players play at the same time,
each with their own Kong. The second Kong stands by (and auto-catches-up when
separated) until player 2 first touches their controller, then stays fully
playable, including after landing. Both players use normal bright colors and
can attack enemies; Player 2's roll, stomp and bounce are covered by a private
first-level replay, along with contact damage and a Player 1 attack regression.
Roll/stomp recovery restores walking and jumping. Held barrels follow and
launch from their owner, including throws across different platform heights.
Either player can walk up to their partner and press SNES A (keyboard
X by default) to carry them. Pickup requires both Kongs on foot and within
24 game pixels horizontally and 16 vertically. Press A again to put them down,
or Y to throw them. The carrier keeps their own controls; both players regain
independent movement after release. Diddy/Dixie and Donkey/Kiddy checks cover
near/far pickup, carrying, drop/throw and save/load.
Each player can grab and climb ropes independently, with climbing animations
in both directions. Single/double-rope junctions complete normally, including
when loading a save already stuck at the end of a transition. The Topsail Trouble
regression covers Player 2 attaching, both players climbing in opposite
directions, save/load and jumping to the neighboring rope. To repeat it with
the private reported snapshot, configure DKC2_COOP_ROPE_STATE with its
external path and run the supplied_rom_coop_ropes CTest check. Adding
DKC2_COOP_ROPE_JUNCTION_STATE enables the second reported checkpoint's
double-rope animations, side exits and transition save/load checks.
It also checks crossing the entire net and reversing direction to reach both
outer ropes without repeating the turning animation in place.
A hurt Kong completes its departure and waits for a DK barrel; pressing its
controls or loading a save cannot revive it. The survivor continues without
the original TEAM turn-taking prompt. A DK barrel restores independent control.
Private checks cover both Kong roles after a leader swap and save/load across
loss, revival and a second loss.
Either player can mount Rambi; the rider becomes the camera leader and keeps
their own controller. The other Kong retains on-foot movement. Private checks
cover riding, jumping, dismount/remount, passing Rambi from P1 to P2 and loading
while mounted. Death handoff keeps the survivor in place and resumes enemies.
Both players can collect banana trails while the other rides Rambi; overlapping
hitboxes and revisiting collected bananas after save/load award each only once.
Both Kongs can move into the visible side areas in 16:10 and 16:9, with the
level walls retained. The camera still follows the active Kong; this is
shared-camera local co-op.
Full-game death/respawn, other animal types and special throwables remain unverified.
The "2P Team mode" choice in the overlay's Settings
page (or
CoopMode in launcher.cfg, or DKC2_COOP=simultaneous|classic) restores
the classic alternating behavior; 1 PLAYER and "2 PLAYER CONTEST" are never
affected.
In-game overlay and Assist Tools
Press Escape during gameplay to pause on a completed frame boundary and open the Dear ImGui overlay. In a fullscreen SDL/Mac game window, the first Escape returns to windowed mode without also opening the overlay; Escape then retains its normal overlay behavior. The SDL host also accepts the controller Guide button; Start+Back is the portable fallback. The overlay provides Resume, Settings, Controls, Assist Tools / Cheats, Credits, and Quit. Gameplay input and audio are paused while it is open. Its first placement is centered from ImGui's logical display size, including on Retina/high-DPI windows, and the title bar can then be dragged to reposition it.
The Settings page exposes the launcher's display, audio, filtering, screen
model, widescreen, skip-launcher, and Restore Defaults choices. Volume,
widescreen, texture filtering, screen model, Player 1/2 source/deadzone, and
the Assist gate apply immediately; window scale, fullscreen mode, renderer,
audio enable, and skip-launcher take effect on the next launch. The shared
sample-rate choice is mirrored and
persisted, but this host currently outputs the SNES-native 32,040 Hz only.
The Controls page has Player 1, Player 2, Assist, and Fixed Shortcuts tabs.
Player tabs expose source, deadzone, and all 12 SNES keyboard/controller
bindings. The Assist tab edits Rewind, Fast-forward, Save State, and Load
State bindings. Select a binding and press the replacement key, controller
button, or axis; controller capture waits for a neutral release first to avoid
recording the button that opened the editor. Changes apply immediately and
are written to launcher.cfg on clean exit. Per-player and Assist reset
buttons restore only their respective control defaults. Escape cancels an
active capture; the menu and performance shortcuts are listed read-only so
they cannot be made unreachable.
Rewind, fast-forward, the overlay's five save-state slots, and every configured
Assist shortcut are intentionally gated behind Enable Assist Tools /
Cheats. This setting defaults off, persists as AssistTools in
launcher.cfg, and adds (Assist Tools: On) to the game window title. On the
native Mac app, the Game menu's fixed Quick Save State and Quick Load
State commands always operate Slot 1, even when Assist Tools are disabled.
The overlay is available in the Windows OpenGL and GDI presenters and the SDL/OpenGL host. GDI draws ImGui through an SDL software renderer into the completed game buffer before presentation, so Escape and Game > Settings / Controls work with the compatibility renderer too.
The pre-boot launcher now also has top-level Assist Tools and Credits sections beside Settings. Credits text is supplied by this project rather than hardcoded in recomp-ui.
The Settings page has a fixed Restore Defaults button. After confirmation, it restores the complete DKC2 launcher configuration: window/display choices, audio, controller sources/deadzones/bindings, Assist bindings, and the skip-launcher preference. The selected ROM, cartridge SRAM, save states, and rewind history are not deleted or replaced. The restored choices are persisted when Play is pressed.
Video settings
The launcher defaults to the OpenGL presenter with nearest-neighbor sampling and the Raw screen model. Raw is a byte-exact presentation bypass. The opt-in CRT, Composite, and Trinitron choices apply the present-time screen-color lookup table used by PSXRecomp: CRT models a consumer SMPTE-C-like phosphor gamut, display gamma, luminance, and black floor; the other two retain the corresponding upstream variants. This model changes color response only; it does not add scanlines, curvature, a bezel, or persistence blur.
The experimental aspect selector is available in the pre-boot Settings page, the in-game Settings tab, and the native Mac View > Aspect Ratio menu. Authentic 4:3 remains 256x224, Mac-oriented 16:10 uses 308x224 (26 added source pixels per side), and 16:9 uses 342x224 (43 per side). Both wide choices preserve the original center. Pirate Panic's collision-bearing foreground margins use DKC2's live decompressed WRAM level map to reconstruct exact 8x8 tiles, with world-keyed history retaining game-authored updates. The adapter accounts for the game's 256-pixel map/camera origin difference, its rotated column buffer, and the one-frame WRAM/PPU latch difference that can occur while the camera crosses an 8-pixel row. Terrain shadow Y unwraps the PPU's tile-aligned origin before restoring the fine phase, and the world-keyed store retains 1,024 tile rows so tall vertical rooms such as Topsail Trouble keep their second epoch.
Every other margin decision is a property of the live PPU geometry, not a
level list. Each enabled bounded background (a 32-column tilemap, or a
64-column allocation whose extension page is another enabled layer's map),
whether enabled for the whole frame or only inside an HDMA band, repeats
its rendered native scanline, which is exactly what a wider PPU
would draw from a map that wraps at 256 pixels. A bounded backdrop kept in a
64-column allocation continues each line at the period its own rendered
pixels prove, so a 96-pixel cabin wall does not restart every 256 pixels,
and rebuilds its stale endpoint pixels from that period; 32-column maps keep
their exact hardware wrap. A 64-column BG3 with pages of its own
renders its authentic adjacent columns; the ship-deck rigging, which the
cartridge streams into that ring with no lead, is instead decoded from its
ROM map into a third world-keyed store after the decode has reproduced every
fully uploaded native column of the current frame. The lava geyser steam of
Red-Hot Ride, a bounded 32-column BG3 the cartridge draws only for geysers
inside its own view, is decoded from the stage's ROM geyser list and
animation tables into the same store, so a geyser beside the view keeps its
column and the map's 256-pixel wrap no longer puts steam over solid rock.
A static 64-column plane that the cartridge never streams (the lava
stages' foreground rocks and far spikes) continues into the margins as its
own hardware wrap once its content proves it is authored to wrap.
Rolling BG1/BG2 terrain layers are classified per HDMA scanline band, read
from the cartridge's own HDMA tables before drawing: a band at the terrain
phase is served from the one world-keyed terrain store (the second physical
layer reads it through an alias view), and any other band repeats its
rendered line, so the lava stages' BG1/BG2 exchanges need no special case.
At a hard level wall the 4:3 edge stays pinned at the wall, so nothing past
the level is ever shown, and the inward view is released gradually over eight
margins of camera travel (edge policy glide, the default). Three
alternatives are selectable from the pause menu's Settings page ("Level
edge"), the WidescreenEdge key in launcher.cfg, or the
DKC2_WIDESCREEN_EDGE environment variable: reflect keeps the view locked
to the game's camera and mirrors the nearest authored columns into the
unauthored strip; bars keeps the view locked and leaves that strip black;
shift is the earlier inward clamp, whose view stands still for the first
43 pixels of camera motion away from a wall while the HUD slides with it. The presented native viewport is exact under
every policy.
Unknown layouts remain transparent rather than guessing.
The original 4:3 mode is the default.
The widescreen adapter reads DKC2's live gameplay sub-mode before choosing a
terrain-map policy. Proven horizontal stages decode the game's column-major
map, and proven vertical stages decode its row-major map. Bramble Scramble's
sub-mode $10 uses a distinct 48-metatile/$60-byte square layout confirmed
against 954/957 visible BG1 cells. Ordinary wasp-hive sub-mode $03 calls the
same cartridge square scroller and now exposes that terrain path
experimentally; Parrot Chute Panic retains its separate narrow-row layout.
Ship-hold sub-mode $02 also uses the rolling row/column DMA path, but its
source map is 80 metatiles wide; Lockjaw's Locker's exact state matched all
957 sampled visible BG1 cells under that decoder. Treating the room's
64-column VRAM ring as a complete static map was the cause of the missing and
unrelated edge strips during movement.
Hornet Hole, Rambi Rumble, and King Zing still need route and per-layer visual
acceptance. Other square rooms and special handlers remain centered until they
have reference-backed reconstruction and route coverage; a 64-column PPU
tilemap alone is not sufficient evidence that a screen is safe to widen.
All three neutral-input attract demos now retain true 16:9 gameplay. Mainbrace
Mayhem uses its existing vertical BG1 terrain reconstruction and repeats the
authentic BG3 cloud/lighting scanline, removing the former 4:3 brightness
seams. Rickety Race uses the established horizontal policy. Parrot Chute Panic
uses the disassembly-confirmed alternate wasp-hive handler: its BG2 terrain is
decoded as a 512-pixel-wide row-major map with 16 metatiles ($20 bytes) per
row, while its cyclic BG1/BG3 hive artwork repeats after normal PPU rendering.
Representative early/middle/late captures are full width, and a 12,000-frame
run completes two ordered attract cycles with zero sequence errors. Final
normal-speed owner validation remains required.
The common DKC2 object activation/despawn and sprite-render boundaries have
been widened, and Pirate Panic has deterministic composite, per-layer, and OAM
margin evidence. Those widened object bounds activate only after the terrain
source for the frame has been verified. This is not yet a whole-game
widescreen certification:
vertical stages, bosses, bonuses, maps, Mode-7 screens, and special effects
still require explicit route testing. The complete recorded Pirate Panic route
and two late BG1 margin regressions pass deterministically. The newer regression
clears source-map cells proven transparent on every frame while preserving
current dynamic game writes, removing stale deck fragments without flattening
ship details. Horizontal source-page calibration improves the sampled frames
at 12,000 and 12,300, which the owner accepted, but frames 12,900, 13,800, and
15,900 remain open visual defects. Physical 64-column BG3 ship rigging can now
render in the margins after the same exact terrain-readiness gate; synthetic
coverage includes Pirate Panic's and Rattle Battle's shared ship-deck PPU
signature, while normal-speed route acceptance remains separate.
Topsail Trouble's supplied exact state is separately accepted at 308x224: its
isolated BG3 rain now reaches both 26-pixel margins, and the original 256-pixel
center is pixel-identical to the pre-fix render. Its later lower-camera Quick
Save is also accepted: exact BG1 terrain now fills both margins through tile
row 540, and the native center is pixel-identical to the 4:3 oracle. A
fresh-entry moving route is still required before treating the complete stage
as closed.
The private Rambi route additionally retains an 8-pixel horizontal guard and
the tile-aligned vertical epoch correction. Exact frames 6,509, 6,511, and
6,512 no longer produce the previous 1,120-sample blank-margin bursts; final
normal-speed owner validation is still required.
Use
DKC2_WIDESCREEN=1 for a
one-process developer override without changing launcher.cfg.
The private 3,134-frame bramble-01 route now exercises Bramble Scramble's
entrance, horizontal movement, vertical climb, and late-stage area. Its BG1
terrain reconstructs into both margins, bounded BG2 uses the existing
rendered-scanline repeat, and BG3 remains clamped because the audited composite
does not expose a gap. The route records sprite output in both margins and
finishes with zero sequence/runtime errors, but it ends before the level goal;
entrance-to-goal acceptance and normal-speed owner testing remain open.
Collectible bananas are a separate cartridge subsystem, not ordinary entries
in the common game-sprite table. Their list traversal and clip span receive the
same fail-closed widening, while a banana-only coordinate adapter supplies
OAM's ninth X bit for positions $0100-$012A. Without that adapter, a banana
at widescreen X=291 was submitted as X=35 and appeared on the wrong side of
the screen. The private bg-02 frame-2,582 replay now places both banana tiles
at X=291 in the right margin. A separate native negative-X tile cutoff has
also been extended through the left margin: the full marsh replay now records
banana tiles at X=-43..-1 rather than only X=-14..-1. Both adaptations remain
off in 4:3; other dedicated object/effect renderers still need route-by-route
audit.
The private bg-01 route confirms why policies must remain screen-specific:
a later forest screen streams its collision terrain to BG2 $7800, not BG1
$7000. Widescreen reconstruction now matches live $17B6 to the enabled
BG tilemap base and prefills the selected layer. Deterministic frames 4,500 and
4,800 now contain the missing BG2 terrain without the prior colored BG1 margin
cells. The automated classifier still flags a sparse secondary BG1 margin, so
owner motion testing and screen-specific foreground auditing remain required.
Mudhole Marsh additionally opts its cyclic BG3 $6C00 forest backdrop into
scanline repetition. This fills the formerly flat-colored margins without
reading unseen BG3 tilemap columns. Other BG3 uses remain conservatively
clamped until audited.
The subsequent bg-02 vertical-motion recording exposed a separate
engine-level row-association error. DKC2 stages the rolling terrain tilemap one
256-pixel page above camera Y. The active BG1/BG2 terrain shadow now keys live
viewport captures, VRAM uploads, and exact prefill in the same rendered PPU
source-row domain. This follows the live terrain destination and is therefore
not hardcoded to Mudhole Marsh, but screens that do not use the standard
rolling terrain streamer remain intentionally excluded.
The GDI compatibility renderer remains selectable and is also used
automatically if OpenGL initialization fails. Screen-color selection is
renderer-independent, so CRT produces the same transformed source pixels on
both presentation paths. Nearest/Bilinear controls only how that completed
frame is scaled. Settings persist in launcher.cfg; Raw remains the default
unless the user opts in. For repeatable diagnostics, DKC2_SCREEN=raw, crt,
composite, or trinitron overrides the saved screen model for one process.
Both desktop hosts offer experimental Reconstruct scaling. In the regular
DKC2Recomp.exe, select OpenGL and restart if currently using GDI; all five
reconstruction levels and the edge strength, softness, and smooth shading
sliders then apply live. DKC2RecompSDL.exe supports the same shader. The
shader source is shared, and all four screen-color presets compose with it.
The shader keeps pixel edges sharp at any
fractional scale, decodes the checkerboard and line dithers SNES artists
used for mid-tones, and rebuilds diagonal edges of the pre-rendered art
with an xBR-style corner test evaluated per output pixel, then softens
the result: wider transition bands and gradient shading where neighboring
colors are close. Its mode combo adds the stages one at a time and sliders
scale the edge blend, the softness, and the shading;
DKC2_UPSCALER=nearest|bilinear|reconstruct overrides the saved choice in SDL.
The Settings page's Display combo switches the Mac app from the flat
panel presentation to an optional CRT television simulation
(docs/CRT_DISPLAY_PLAN.md is its design). It is not a scanline overlay:
every source line becomes an electron-beam profile whose width grows with
its brightness, so bright lines widen and merge while dark lines stay thin,
and the beam is normalised so the picture keeps its brightness. A fine
aperture-grille phosphor mask (three panel pixels per triad, below the eye's
resolving limit at arm's length), a soft glow and halation from blurred
copies, a gently curved tube face with rounded corners, and a dither finish
the look. "Living room" is the default preset; "Studio monitor" is sharper
and flat, "Soft" is wider and glowier, and the sliders (scanlines,
sharpness, mask, glow, halation, curvature) make a custom tube. The
upscaler is bypassed while the tube is on, and the tube fades to the flat
image in small windows where its lines cannot be drawn.
DKC2_DISPLAY=flat|crt, DKC2_CRT_PRESET=living-room|studio|soft, and
the DKC2_CRT_* sliders override the saved choice. The frame after the
phosphor-color model is the tube's input, so those models still apply; the
native frame, its hashes, and save states are untouched.
Visible OpenGL gameplay windows on Windows request a one-buffer swap interval
to reduce tearing. The accepted status is written with the presentation
backend in diagnostics/last_run_report.json; on means the graphics driver
accepted the request, while request-failed or unsupported means it did
not. Hidden automation disables the request so driver pacing cannot block
unattended tests, and GDI synchronization remains managed by the Windows
compositor. The Mac app instead paces each frame on the display's own refresh
tick and keeps the audio in step with dynamic rate control, so every frame is
shown for exactly one refresh on a 60-Hz or ProMotion display;
DKC2_DISPLAY_LOCK=0 returns to the host clock and DKC2_PACING_LOG=<file>
records the cadence for scripts/analyze_pacing_log.py. Neither changes the
emulated 60.098811862 Hz clock.
Save states are named saves/dkc2s0.sav through saves/dkc2s4.sav; the
overlay presents these as Slots 1–5 and the native Mac Game menu uses Slot 1.
On macOS this relative directory lives under
~/Library/Application Support/Flat2VR/DKC2Recomp; portable builds keep it
beside the executable. The first slot still loads the former
saves/dkc20.sav name as a compatibility fallback, but all new writes use the
unambiguous names. States are separate from the cartridge SRAM files used for
normal in-game saves.
The launcher and game window use the development title
DKC2 Recomp Alpha Pre-Release; the game window appends the measured
presentation rate once per second.
Press F to write per-phase main-thread timings to performance.log beside
the executable; press it again to stop. The log identifies the active OpenGL
or GDI backend and selected screen model. It measures CPU time spent submitting
presentation work, but neither path currently collects GPU timestamp queries,
so GPU time remains explicitly unavailable instead of being reported as zero.
Crash reports and support bundles
Both playable hosts maintain diagnostics/last_run_report.json beside the
executable. A runtime failure or native Windows exception also creates a
timestamped diagnostics/diagnostic_bundle_* folder; Windows exception bundles
contain a minidump. Set DKC2_DIAGNOSTIC_BUNDLE=1 before one launch to request
the same support folder after a clean exit.
Bundles use a strict allowlist: the JSON report, instructions, an optional
launcher.cfg, an optional performance.log, and an optional Windows
minidump. They never copy rom.cfg, ROM bytes or paths, generated game code,
SRAM, save states, screenshots, or audio captures. Loaded program-module paths
and basic operating-system/hardware information are included, so inspect the
folder before sharing it. See
docs/DESKTOP_TESTING.md for the crash drills and
platform behavior. Mod-aware save isolation remains deferred until a real mod
manifest and loader exist; current save locations are otherwise unchanged.
First-level route testing
Pirate Panic is the next gameplay correctness target. The desktop host can
record per-frame input with SNESRECOMP_INPUT_REC, and the headless host can
replay it with SNESRECOMP_INPUT_PLAY. The new private route gate checks that
the replay enters Pirate Panic, stays active, changes the completion flags,
triggers a level-exit transition, and keeps audio unclipped.
Recordings should live in ignored private storage such as recordings/ or
private/. See
docs/FIRST_LEVEL_ROUTE_TESTING.md for
the exact recording and replay commands. The first captured route reaches the
goal, but the native replay currently exposes an unresolved dispatch at
$BA:B33F; Roadmap #2 remains open until that path replays without an
interpreter-cap or unresolved-dispatch diagnostic.
Static recompilation coverage
The current analysis profile has 3,325 roots across 13 banks. It emits 3,475 exact CPU-mode variants as static C and retains two deliberate original-game fault variants on LLE. This is compile-time structural closure, not a percentage of dynamically executed CPU instructions and not a claim that the shared interpreter can be removed.
The interpreter remains the safe runtime default for an unavailable exact entry state. Two dormant bugs in the original game also deliberately preserve their real JSR stack frames and hand control to the interpreter if reached: both calls enter bytes documented as data/garbage and crash on original hardware. They are explicit exceptional LLE edges from compiled callers, not normal game logic and not guessed native implementations.
The generated C remains ignored because it is derived from the user's ROM. Only source-owned configuration and structural metadata are committed.
Runtime-selected entry coverage
The structural-closure figures above cover every entry state demanded by the
static graph; they do not prove that every address selected later from mutable
game data was already named as a root. An owner-recorded Version 11 session
exposed that distinction in Swanky's Bonus Bonanza. The process exited cleanly,
but runtime state $B4:A4CB reached the interpreter's 2,000,000-instruction
safety cap and appeared interactively as 1-3 FPS.
The source configuration now declares Swanky's states $B4:A3E0, $B4:A475,
$B4:A4CB, $B4:A5D9, and $B4:A665, plus helper $B4:A7CA, as explicit
AOT roots. The shared call bridge also preserves the handler's intentional
non-local return: in 16-bit accumulator mode, PLA consumes the paired JSR
frame and the following RTL consumes an outer JSL frame. That return must
unwind the compiled caller rather than resume code the game deliberately
skipped. The shared-bridge regression passes 62/62 checks. DKC2 regeneration
and both optimized Release and trace builds now succeed, and the generated
dispatch table contains all six exact entries.
Rolling diagnostic reports now preserve the last 1,024 runtime indirect
dispatch events. scripts/validate_swanky_run.py requires a native M0X0
dispatch from the Swanky dispatcher to $B4:A4CB, rejects interpreter caps,
missing Swanky AOT entries, the original corrupt sequence, and execution in
SNES MMIO addresses. Its synthetic regression passes and it correctly fails
the original Version 11 artifact. The complete available suite is 52/53; the
only failure is the unchanged supplied-ROM frame-3,309 sprite-reference
mismatch. The owner's fresh normal-speed game-show check remains pending.
Input files record the resolved controller word for each forward emulated
frame. They do not encode host rewind or save-state save/load actions. Fast
forward remains recordable because every forward emulated frame is sampled,
but a route that rewinds or loads a state cannot be reproduced from its
.input and starting SRAM alone. Capture focused regression routes without
those actions until the recording format gains an explicit host-action stream.
Building from source
Prerequisites on Windows:
- CMake and Ninja;
- a C/C++ toolchain (MSVC or MinGW-w64; an installed SDL2 package is optional);
- Python 3.9+; and
- Rust/Cargo for the native whole-program analyzer.
git clone --recurse-submodules https://github.com/mstan/DKC2Recomp
cd DKC2Recomp
.\scripts\generate_snesrecomp.ps1 -Rom "C:\private\dkc2.sfc"
$env:Path = "C:\msys64\mingw64\bin;$env:Path"
cmake -S . -B build-release -G Ninja `
-DCMAKE_BUILD_TYPE=Release `
-DDKC2_BUILD_SNESRECOMP=ON `
-DSDL2_DIR=C:\msys64\mingw64\lib\cmake\SDL2
cmake --build build-release --target dkc2_snesrecomp_desktop
The build can fetch the pinned SDL 2.30.9 source when an installed SDL2 package
is unavailable, so SDL2_DIR is optional. Windows also builds the portable
host as DKC2RecompSDL.exe with target dkc2_snesrecomp_sdl.
Linux and macOS use the portable generator and SDL gameplay target:
python3 scripts/generate_snesrecomp.py --rom /private/path/dkc2.sfc
cmake -S . -B build-release -G Ninja \
-DCMAKE_BUILD_TYPE=Release -DDKC2_BUILD_SNESRECOMP=ON
cmake --build build-release --target dkc2_snesrecomp_sdl
./build-release/DKC2Recomp /private/path/dkc2.sfc
The checked-in recomp/bank*.cfg files already contain the active,
revision-validated disassembly names used in generated C and trace logs. A
private WLA symbol overlay can conservatively expand remaining CODE_...
names without copying the overlay into the repository:
python .\scripts\promote_snesrecomp_symbols.py `
--cfg-dir .\recomp `
--symbols .\private\dkc2-yoshifanatic-v1.sym
# Review the dry run, then apply the same validated set.
python .\scripts\promote_snesrecomp_symbols.py `
--cfg-dir .\recomp `
--symbols .\private\dkc2-yoshifanatic-v1.sym `
--apply
The tool only accepts an unambiguous context_CODE_BBXXXX alias that retains
the original generic identity. It rejects bank mismatches, collisions, and
ambiguous aliases; raw same-address matching is intentionally unsupported
because revision-dependent layout changes can shift dense dispatch tables.
Regenerate after applying so recomp/funcs.h and private generated C receive
the new names.
The SDL host is runtime-tested on Windows. Linux and macOS are not called
supported releases until their native acceptance matrices pass. See
docs/CROSS_PLATFORM.md for prerequisites, exact
commands, implemented features, and the remaining platform gates.
Project-owned desktop and headless code is compiled for speed in Release
builds (-O3 with GCC/Clang and /O2, MSVC's maximum speed preset, with
MSVC). To embed a private Windows .ico without adding it to Git, configure
with -DDKC2_DESKTOP_ICON="C:\private\dkc2.ico".
Create the next source-clean, user-testable Windows snapshot with:
.\scripts\create_windows_version.ps1
The first run creates versions\Version 01, the next creates
versions\Version 02, and so on. Existing numbered folders are never deleted
or overwritten. Each folder contains both playable Windows hosts, the required
launcher assets, documentation, and a VERSION.txt provenance/hash manifest.
Normal packaging refuses uncommitted source; -AllowDirty is available only
for an explicitly marked development snapshot.
The packager allowlists the documented launcher cover and refuses ROM, save,
generated, diagnostic, configuration, screenshot, and audio artifacts. The
compiler continues to reuse its normal build tree; only testable handoffs are
duplicated, avoiding multi-gigabyte source/build copies.
For private play testing, create a second copy outside the repository after the normal version has been packaged:
.\scripts\create_personal_test_version.ps1 `
-PublicVersionDirectory "versions\Version 05" `
-RomPath "C:\private\dkc2.smc" `
-SavesDirectory "build-snesrecomp\Release\saves" `
-LauncherConfigPath "build-snesrecomp\Release\launcher.cfg"
The helper verifies the exact supported ROM hash and, by default, creates
..\DKC2 Personal Test Builds\Version NN with a relative rom.cfg, the ROM,
the selected saves, and optional launcher settings. It refuses destinations
inside this repository and refuses to overwrite an existing private version.
These personal folders must never be committed, uploaded, or attached to a
release.
For the current widescreen investigation, a private diagnostic version can be created directly without making a redundant public package:
.\scripts\create_private_diagnostic_version.ps1 `
-RomPath "C:\private\dkc2.smc" `
-Sequence 10
It assembles the normal and trace executables, verified ROM, saves, existing
private recordings, launcher settings, control bindings, and capture helpers
outside Git. Its bundled Record-Pirate-Panic.ps1 preserves starting SRAM,
refuses reused evidence names, and requires fresh performance, tier-2, and
last-run reports; Diagnose-Frame.ps1 then creates an isolated same-frame
layer/object report. The focused Swanky validator is packaged under tools/.
See
docs/BUILD_HYGIENE.md and the package's
TESTING_README.md.
Use build-snesrecomp/ as the single routine Windows compiler workspace and
launch manual-test builds only from versions/Version NN/. The older
build* folders are explained and classified in
docs/BUILD_HYGIENE.md; they are not additional source
versions.
Repository layout
recomp/— source-owned CFG and structural metadata.runner/— DKC2 host adapters, input, presentation, rewind, and ROM checks.snesrecomp/— pinned shared recompiler and SNES runtime. The submodule currently uses theNicktendonick/snesrecompintegration fork so its DKC2-specific commits are fetchable;mstan/snesrecompremains the authoritative upstream.recomp-ui/— pinned shared Dear ImGui launcher. The submodule currently uses theNicktendonick/recomp-uiintegration fork so its configurable DKC2 binding ABI is fetchable;mstan/recomp-uiremains authoritative.docs/RECONCILIATION.md— provenance and disposition of the pre-upstream working tree.docs/CROSS_PLATFORM.md— SDL host builds and native acceptance gates.docs/BUILD_HYGIENE.md— canonical build, output, and test-version policy.docs/WIDESCREEN_DIAGNOSTICS.md— deterministic layer/object evidence bundles and the terrain-first widescreen debugging workflow.scripts/— regeneration, testing, packaging, and launch helpers.generated/,private/, and build directories — ignored local artifacts.
Acknowledgements
- H4v0c21's DKC2 disassembly provides the independently verified symbols and structural boundaries used during analysis. No disassembly or ROM-derived assets are redistributed.
- snesrecomp provides the static recompiler, interpreter fallback, and shared SNES runtime.
- recomp-ui provides the shared Dear ImGui launcher.
- The optional screen-color LUT is adapted from
PSXRecomp at the pinned revision and
implemented by the shared SNESRecomp color-LUT module. It retains its
upstream license and JRickey/gba-recomp attribution under
third_party/psxrecomp_color_lut/and in the submodule's matchingthird_party/notice directory. - The SNES hardware implementation derives from LakeSnes, with additional algorithms credited to Snes9x in the relevant source files.
License
Project-owned source is available under the MIT License. Vendored
dependencies and submodules retain their own licenses. In particular, the
PSXRecomp-derived screen-color component is PolyForm Noncommercial 1.0.0 with
an MIT/Apache-2.0 color-science lineage; the complete notices are in
third_party/psxrecomp_color_lut/ and it is not relicensed by the root MIT
license. Nintendo and Rare
own their respective game content and trademarks; no license in this
repository grants rights to that content.
Display and controller parity with DKC3 is recorded in DKC3_FEATURE_PARITY.md. Both hosts now expose 21:9 (446x224) alongside 4:3, 16:10, and 16:9. Stomp rumble and separate P1/P2 test pulses are in Escape > Settings, with controller routing matching input assignment (keyboard P1 plus gamepad P2 uses that gamepad for P2 feedback). Physical rumble sensation and full-game ultrawide coverage require further play.
