Need help getting started? Try the player guide. These notes include older work; the game overview explains what’s ready now.

Native port findings

Sprite shadows (2026-10-21): Graphics now offers independent size-scaled player/enemy/item billboard sprites, Off by default, in all three renderers. Each shadow is drawn immediately behind its subject with wall silhouette clipping; the former floor-projected sampling pass has been removed. Settings v19 preserves the16-byte record and reads v1..18. Visual-effect rows are88/96/104/112; Back remains144. See sprite-shadows.md.

Graphics now holds Surface decals, Water reflections and Godrays below Mipmapping. Extras retains eight gameplay/presentation rows. Saved values, defaults and v18 settings layout are unchanged; all three effects remain available in GBA, Software and Vulkan.

Settings now has one Mouse sensitivity slider above FOV, with 10..300% range and100% preserving the previous64 heading-units/count speed. The shared horizontal/vertical value applies immediately and persists across levels. Settings v18 retains16 bytes and the CRC, using a compact header/payload while reading v1..17 unchanged; v1..17 mouse values migrate to100%, and v18 uses its saved horizontal value. See mouse-sensitivity.md.

Extras now has an independent Godrays toggle below Water reflections, default Off for fresh settings. Settings v17 preserves the16-byte CRC layout, reads v1..16, and migrates the previous coupled Surface decals choice to Godrays. All three renderers and reflections honor the separate choice; see surface-decals.md.

Graphics now offers original-asset mipmapping for Software and Vulkan, locked On for GBA. World textures, sprites and reflected scenes use the ROM's existing mip images. Settings v16 preserves the16-byte format and reads versions1..15; fresh settings enable mips while migrated native preferences retain their previous appearance. See mipmaps.md for selection and validation details.

Vulkan is now an optional Windows hardware scene backend, selectable in Graphics when available. Walls, floor/ceiling polygons, actors and mirrored scenes use GPU rasterization; HUD, decals/water composition and presentation retain their CPU paths. Software/GBA remain available and settings versions1..14 remain readable. See vulkan-renderer.md for architecture and focused evidence. The initial severe Vulkan stall is corrected: dedicated cached readback, bounded parallel effects, amortized buffer growth and visible-row reflection transfers. scripts/bench-vulkan.ps1 measures isolated render time; reflections remain the heaviest case. Resolution, artwork, simulation and audio timing are unchanged.

Technical audit follow-up: save-read failure handling, locked audio status, a shared decal atlas, separate scene/HUD link targets, centralized runtime settings, and focused incremental tests are implemented. The latest render-loop pass combines GPU sample processing, skips overwritten clears and reuses identical sky rows, with exact before/after outputs and measured lower render times. See technical-refactors.md for scope, measurements, and validation; frontend separation remains incremental.

Current milestone: all twelve campaign levels are enabled through play-native.cmd. Extras now offers a saved Original/Classic HUD choice, defaulting to Original. Classic reconstructs the retained green interface with live health, armor, ammo, score, saved/live high score, time, unread NETRICSA entries and boss health in both renderers. It adds a transient weapon selector, health/ammo palette flashes and static white localized notices. New dossiers blink the retained analyzing sprite in HUD green without backing near the upper center for2s, then teleport the green/white inbox inward, hold2s and teleport back. Duplicate entries do not retrigger it. Classic's other anchors now follow the Serious Engine layout with2px edge insets, spaced armor/health, separate finite/infinite weapon positions and a higher selector. The former top-center timer panel now shows max(saved high score,current score), inset2px vertically; the timer sits immediately below. Weapons and crosshair keep their existing behavior. See classic-hud.md. The shared original sprite compositor now accepts mixed priorities, including transparent-sample priority promotion, instead of rejecting the frame. Both renderers benefit; see display.md for the bounded hardware-model evidence and native/Windows checks. The Main-menu Scores screen now includes original ranking/name entry and saved records, with keyboard typing, original cycling and record highlighting. Pause Quit and campaign-ending handoffs offer qualifying scores; see scores.md. Death now consumes a life and automatically retries from the level-entry snapshot. Retries skip NETRICSA and the map, starting directly at the normal black-to-level fade with the ready weapon, HUD and movement available. The final life runs the original Game Over message/music before the black fade and Main return. A stale pause bit cannot stall the death controller. See run-exit.md. The automap now opens with M in both renderers, gated by the saved Automap On/Off option in Extras (default Off; explicit saved choices retained). Mouse wheel or held plus/minus zooms; live geometry, markers, contacts, palette and scanlines run in native C. Tab retains NETRICSA. See automap.md. Jump now defaults to Off in Extras. Existing explicit saved choices are preserved. Native NETRICSA now toggles during gameplay with Tab; N opens/closes and Esc returns. It also precedes every pre-level map view. In-game NETRICSA overlays a frozen full-resolution game frame; only pre-level NETRICSA uses the animated background. In-game fades take250ms; pre-level NETRICSA retains its original fade speed. The in-game blend removes HUD sprites except the weapon while darkening and tinting the frozen level green; closing reverses the blend. Original weapon/enemy illustrations, localized descriptions, two scrolling panels, strategic/tactical records and live/campaign-session statistics are connected. Enemy dossiers unlock only after a kill. A campaign-session journal tracks weapon/enemy discoveries and individual read status across levels and retries; Classic's top-right panel displays the combined unread count. Every level's starting equipment is familiar: viewable, automatically read, without a new-message count or notification. Actual in-level discoveries still alert, and carried unread messages retain their status across level changes. NETRICSA freezes gameplay. Pre-level briefings use the original music cue; in-game opening/closing preserves the current music's uninterrupted playback. See netricsa.md. On2026-10-17 the user explicitly requested manual campaign validation rather than gating levels on automated playthroughs. The final map, Caesar's Palace, now participates in normal advancement, passwords and saved level selection. Existing saves remain compatible; beat map10 to unlock map11, or use play-native.cmd --level 11 for a direct standalone start. The original campaign story controller19458/193D8/1965C and its native screen now connect Egypt/Rome/ending panels, artwork, text, music and fades to the frontend. The controller passes50,462 ROM comparisons; text adds1,018 original row comparisons, with87,854 native screen assertions and three Windows paths. The final completion tally leads into the ending and returns to Main. Esc/P now opens the native pause menu. The original time/ammo tally, bonus score carry and final Sam text/music hold are connected; high-score/name entry remains. See completion.md and campaign-story.md. Original localized HUD notices now connect pickup, boss and death callbacks to both renderers, including cache readiness, layout and shared lifecycle timers. The controller passes135,104 ROM comparisons, native integration passes13,650 checks, and normal-input level1 still completes in5,110frames. See hud-notices.md. The timed completion tally's active notice service is available; its outer screen/digits/audio/record integration remains. Rome maps now retain the original golden ankh, including the full20x34 and distant10x17 images decoded from the ROM. The former laurel override is no longer applied or linked into the frontend. Its artwork is retained as historical material. Advancement now recovers original player construction and weapon restoration: 100 health, zero protection, earned weapons/ammo and score. R retains the exact level-entry snapshot. See campaign-entry.md for 8,192 original restore comparisons and 512 construction/restore sequences on 16 maps. Original completion capture 1231C now runs natively too: another 4,096 ROM comparisons and 512 capture/restore compositions cover gear and per-weapon statistics rows. The original completion-statistics accumulator and checkpoint helpers are now native and byte-matched too. Their read-only native adapter exposes all live counters; campaign-session totals now feed the completion frontend; original high-score lists and name entry remain unfinished. See statistics.md. The timed time/ammo bonus controller and final record pipeline are now recovered too: 11,466 original-loop frame comparisons and 410,217 native composition checks pass. The pause/completion frontend now connects original notices, digits, voice dismissal and campaign-session totals. Active E914/E9D4 message sprites are now recovered and used during gameplay. See completion.md. The later frontend integration connects the timed tally and bonus-adjusted carry to the playable executable. The subsequent targeted cannon fix now detaches player cannonballs at launch, like rockets and Prion shots. Cannonballs retain original no-gravity flight and now continue rolling horizontally on floor contact, without adding airborne gravity. Rockets still explode and Prion shots stop at ceilings. Six launch/trajectory cases per weapon and12ceiling contacts validate these paths; current counts/hashes are in weapon-fixes-validation.json. The default projectile integration and enemy cannon regression also remain covered. The rebuilt launcher/startup/restart checks pass. Full campaign replays were not repeated for this correction. See weapon-fixes.md. Prion-converted enemies now continually select the nearest living combatant, including Sam, other converted enemies and bosses, without player preference. Facing, ranged aim and enemy melee follow that selection. The focused test passes 1,602 checks on GCC sanitizers and Windows across all ten convertible types; special weapons retain 32,318 checks and default entity runtime 85,982. The rebuilt Windows launcher/startup/restart checks pass. See projectile-conversion.md. Campaign figures below are historical replays, before this targeting change. The corrected normal-input chain completes all eleven in 140,712 frames with 1,544,000 score / 45 HP. It includes the latest collision, Prion2x and Time Strike changes. It supersedes the older 136,552-frame full-vitality-carry checkpoint. A retained converted-enemy target pointer exposed an overly strict projectile-adapter guard; cleared/reused stable slots now follow original1097C behavior, with16 native Gunrilla regressions and two directed ROM comparisons. Read native-game.md for the current composition, validation and limits. Earlier sections retain the recovery history and individual subsystem boundaries. The eleventh-level probes found a Time Strike render failure: an animation change while frozen retained a frame from a longer sequence. The native view adapter now supplies a valid frame in its render snapshot, without advancing animation or changing gameplay. Both renderers and views pass the32318-check special-weapon suite on GCC sanitizers and MSVC. Praetorian Fort now completes through normal input with earned equipment and original next-level vitality. A separate Normal standalone test now completes the final map: D8 defeat, original music changes and the VM exit in 17,270 frames with 63 HP. GCC sanitizers and MSVC agree on every standalone field. The final earned-inventory probe dies before the boss, so that map remains unavailable. See native-game.md and special-weapons.md. Weapon7 Prion shots now launch independently on the sight line immediately, including level aim before any pitch input; the old sideways offset is removed. See weapon-fixes.md. Gunrilla cannonballs now clear their own shooter at launch while retaining normal impacts against walls, players and other enemies. See projectile-runtime.md for the scoped collision fix and tests. The playable PC and reference renderers now restore original0750C/0787C bar colors, rather than using the static sprite palette for every row. See hud-colors.md for original-ROM pixel comparisons. Startup/restart now restore the original pre-level map view and its music; simulation, controls and HUD start during the level reveal after the map's black hold, with the level soundtrack. See map-view.md. Original feature parity is the completion target; the full campaign, remaining menus and other documented gaps remain unfinished. Normal startup now goes straight to Title, then Main/Single Player/difficulty. Select Level now appears between New Game and Password, with saved completion unlocks and original localized campaign names (no multiplayer maps). Language persists too. Clear Data in Options uses a Yes/No warning, default No, to reset both. See profile.md for storage, loadouts and validation. Options cycles English/German/French in place alongside music and credits; there is no startup language list. Passwords load the original weapons/ammunition and difficulty on supported maps. See menu.md for coverage and original-ROM proof. The original fixed BG1 grid now overlays the scrolling menu background from the first title/main-menu visit, as requested. Fresh diagnostic level launches now use the ROM's original level-start weapon and ammo records, like password starts. Existing progress takes precedence: advancement retains carried weapons/ammo, and R restores the captured entry. Mouse hover/click now selects menu labels with correct letterbox coordinates; passwords accept direct keyboard text and editing. The menu soundtrack continues across Press Start. Shared pointer/text helpers prepare future NETRICSA and score screens; those screens remain unfinished. Both boss controllers are now connected to the native dispatcher, animation, combat, projectiles, script queues and HUD health binding. The sixth map's D7 fight and scripted completion are verified; later boss-map progression remains unvalidated. Weapons 8/9 and original background/hurt palette effects now bind to native gameplay and both renderers; see special-weapons.md. See enemy-boss.md. Type-64 effects now use recovered wall/sector clipping and sector-only list updates; see sector-clip.md. The validated playable campaign historically covered eleven maps. Admission now includes all twelve by user request. The seventh/eighth are in the second original resource family; their real exits complete through native scripts without grants or shortcuts.

Established input behavior

ROM address Behavior Native implementation
0x08003028 Read active-low KEYINPUT; held/newly pressed edges; reset chord; record/playback selection ssa_input_poll
0x08003150 Pack buttons into one byte and append while count <= 0xE0E ssa_input_record
0x08003298 Expand packed buttons; advance repeat count and RLE stream; 0xFF ends playback ssa_input_playback

These three behavioral ports passed 14,848 differential cases against the supplied ROM's original instructions. The test includes all 1,024 physical button masks, simultaneous opposite directions, all 256 packed values, recording bounds, repeat-count bounds, record/playback priority, state flag gating and reset calls. It does not establish correct full-game integration, rendering or mouse controls.

The input state starts at 0x030042F0:

Offset Observed use
+0x00 Raw held (low halfword), pressed edges (high halfword)
+0x04 Processed held/pressed after recording/playback selection
+0x08 Saved global value during record/playback setup; broader purpose unresolved
+0x0C Recording-buffer pointer
+0x10 Playback-stream pointer
+0x14 Game-state value, not recovered here
+0x1E Recording position
+0x20 Remaining repeat count
+0x21 Current packed playback buttons
+0x22 Reset-related byte cleared when reset chord is absent
+0x23 Bit 1 records; bit 2 plays back; recording has priority

0x03004010 holds a pointer to another object. Bit 0 of its halfword at offset 4 suspends recording/playback. Its broader game-state meaning is not established. The native API calls this input_suspended.

The original recorder resolves simultaneous left/right to left and up/down to up. Select and Start are not encoded in recordings. Playback emits the current buttons before consuming the next run. Raw hardware polling retains the upper six bits of the inverted halfword; masking them early changes reset detection. Native pointers deliberately have host width; the native structure is not a binary-compatible GBA RAM structure.

Matching status and tool fixes

Live matching is 78/526 functions and 2,816/87,648 catalogued bytes (3.21%), after 549 compiler attempts (live status checked 18 October 2026). Original statistics helpers 1CF4, 1D9C and 1E48 add 592 exactly matched bytes. Both export and independent rebuild preserve the original ROM byte for byte.

The manual recorder candidate is 97.5% similar, with the remaining differences at the initial global-pointer/limit/load scheduling. It is not counted among the exact matches. Its best source and notes are stored in decomp.wtf.

The matched catalogue contains 2,816 bytes of verified C out of 87,648 imported function bytes. This denominator excludes undiscovered code. The 8 MiB image size is mostly data and is not a useful code-completion denominator.

Luvdis needed bounded-stack fixes for speculative paths, conservative handling of partial BL instructions it cannot model, and buffered output for WSL. scripts/test_luvdis_stack.py verifies large frames, negative stack positions, ordinary returns and unsupported partial calls. These changes do not modify the ROM. The initial 525-function catalogue was retained after an aggressive additional sweep proposed thousands of unverified starts.

The GBA exporter emitted unresolved Thumb-call labels as untyped absolute linker symbols. GNU ld inserted interworking veneers, overflowing the fixed ROM layout. The local patch emits typed absolute Thumb function symbols in a separate object. The exporter also now discovers unresolved canonical address symbols from C objects, including uncatalogued calls and IWRAM data references. Thumb-call relocations determine function mode; ordinary ARM calls retain ARM mode. This fix is recorded in patches/decomp-wtf-c-externals.patch and applied by bootstrap after the existing Thumb-symbol patch. tests/test_export_c_externals.py checks both patches against the pinned upstream and links real ELF objects to verify symbol types, data addresses and absence of added interworking veneers. The full rebuilt image is checked against the original. Unmatched code remains assembly or original data; the rebuild is not evidence of a complete decompilation.

Earlier recovery plan and subsystem checkpoints

These are older development notes. See What you can play and Playable build details for what you can play today.

Next work required for the requested playable port

The input-to-player path and pre-collision control/vector phase have now been recovered. See analysis/movement.md for addresses, original quirks, native API scope and 106,577 differential cases. This includes heading math and movement velocities. The static collision and move-commit work described below is now implemented; the world integration described below adds the timestep and sliding. The PC event adapter and Win32 backend are now implemented; physical-device validation and the complete game frontend remain. A diagnostic native viewer already runs movement, jump, H camera, world geometry and original actors.

Vertical position/gravity and camera height are now also ported; see analysis/physics.md. Those complete routines pass 31,567 ROM comparisons. The user-requested jump extension is separate native code with 36 behavior scenarios. All 16 map resources now load natively with original wall setup; see analysis/map-assets.md. BSP lookup, static map queries and clearance/move commits pass 62,118 ROM comparisons. Another 16 start-position checks and 32 real-map jump scenarios cover original spawn points and player dimensions. See analysis/geometry.md for the static query scope. Native entity collision, host spatial lists, wall sliding and horizontal timestep integration are now implemented, with 71,808 additional ROM comparisons. See analysis/world.md and analysis/sliding.md. Pickup dispatch and synchronous world removal are now also recovered; scripted effects, combat and OS controls remain.

  1. Expand the function catalogue from actual call targets and validated code ranges. Review ARM startup, hand-written math/render routines and code copied into IWRAM; do not count speculative asset bytes as functions.
  2. Continue into subsequent enemy AI, scripted effects, other gameplay contacts and projectile simulation. Map-object construction 08001984, inventory helpers and type-0xE1 dispatch 0801B99C are now native. The latter still exposes script/audio/HUD/network/nearest/destruction boundaries through callbacks. See spawning.md, inventory.md, pickups.md and updated world.md. Queued acquisition and cycle selection are also recovered and verified; see weapon-selection.md. Requested/current animation handoff and original weapon control now live in weapon_controller.c and weapon_runtime.c. Player initialization 05E4C, complete movement 064B8, frame wrapper 05CCC and entity timer 12CFC are now native. player_runtime.c joins these with native jump and H-camera behavior. Death 06154, respawn 05FEC, spawn selection 01B18 and hazards 05680 are now recovered and connected through player_gameplay.c. Their 40,068 ROM comparisons and 10,016 native integration frames are documented in player-lifecycle.md, respawn-selection.md, player-hazards.md and player-gameplay.md. Moving sectors, switches and the level-script interpreter are now native: another 44,433 ROM comparisons include all 116 real script entries with controlled spawn/effect dependencies. level_runtime.c connects line/sector triggers, mover hazards and script mover commands. Entity updates precede movers, which precede the script VM, as in 0800244C. See level-runtime.md. Scripted creation now uses native pool/world insertion in script_spawn.c; all twelve enemy state-zero initializers are recovered, including boss setup. The pool and activation paths pass 36,697 and 14,576 ROM comparisons. Native script-spawn integration runs all 116 original entries; explicit test defeat notifications unblock groups without pretending to simulate combat. See script-spawn.md, entity-pool.md and enemy-activation.md. Shared navigation, directional walking, hazards and death/corpse handling now compose with the type-CD controller in enemy_cd_runtime.c. Another 121,260 ROM comparisons and 59,319 native integration assertions cover this work; see enemy-cd.md. Its 62-byte outer dispatcher is also byte-identical C. Original visibility B18C, nearest selection 036C4 and wall rays A240/A041 now compose through enemy_queries.c, with 263,969 additional ROM comparisons and 53,384 native integration assertions. See enemy-queries.md. Other enemy controllers remain. Damage 037F4, explosion 035A8 and reward 125E0 now compose through combat_runtime.c, with 155,517 ROM comparisons and 26,435 integration assertions. CD contact damage and chain explosions reach real player/enemy health and death handling. See combat-runtime.md. Weapon animation, all ten firing controllers, auto-aim and hitscan now pass303,556 further original ROM comparisons; see weapon-animation.md, weapon-controller.md, weapon-aim.md and weapon-hit.md. weapon_runtime.c binds hitscan damage and selection to native gameplay. Projectile construction, flight, five controllers, wall reflection and attached conversion effects now pass136,192 ROM comparisons. projectile_runtime.c connects weapons6/7/10 to the shared native pool and combat. Type69 converts enemies to target other enemies and drains health; the previous freeze/thaw interpretation was incorrect. The CD runtime now shares the original drain fields with projectile impact. Projectile68/6A splitting/spread and presentation remain. See projectile-conversion.md and projectile-runtime.md. Aimed constructor109F0 is another48-byte exact match. Original entity scheduling04E04/083E4 now passes72,420 ROM comparisons; entity_runtime.c connects players, CD enemies, projectiles and owned pickup timers in that order of active slots. Integration passes85,982 assertions on all16maps, including jump/H. Other enemy handlers and the complete outer game loop remain. Original initial loadouts1240C pass12,979 ROM comparisons; native startup passes84,077 assertions over608starts and192shots from the original selected weapons. See entity-runtime.md and weapon-start.md.
  3. Continue active text notices, palette/blending effects and remaining sprite controllers. Normal weapon/HUD/OAM composition and original240×160 display sampling now work natively, following D2D0/01828 actors, wall occlusion, solid/portal walls and floor/ceiling/sky. Complete game presentation remains. Replace GBA VRAM, DMA, interrupt and timing operations with native platform interfaces.
  4. Finish platform/mode/level startup integration, asset loading, audio and save handling. Add native keyboard bindings, relative mouse yaw, independent strafe and movement. Determine whether vertical look is compatible with this renderer before promising free-look behavior. The0244C frame and F85C sprite dispatchers now pass10,500 and70,344 ROM comparisons. Actor00908 animation and multiplayer pickup respawn pass218,240 and73,734 comparisons. game_runtime.c composes these with native entities, movers/scripts and weapons, passing997,410 integration assertions with genuine two-player shared lifecycle/input, live local hazard flags and shared CD sound state. Input distribution, mode control and rendering remain external stages. See game-runtime.md, frame.md, sprite-dispatch.md, actor-animation.md and pickup-respawn.md. Actor setter05394 adds a60-byte exact match.
  5. Extend the existing Windows native viewer into the actual full game and verify menus, combat, progression, sound, save/load and original frame timing.

PC event sampling and frame integration now provide WASD, mouse yaw/fire, Space, H and E, with314,726 sanitizer assertions on all16maps. The Win32 event backend passes3,215 MSVC assertions with posted window messages/raw payloads; physical device delivery remains untested. All90 portable libraries plus the Win32 backend build as91 native Windows x64 libraries, plus the native viewer. The viewer is incomplete; no complete game executable exists yet. The local05898 distributor adds183,988 ROM comparisons, with genuine network distribution explicitly unsupported. See pc-input.md and win32-input.md.

All311 original sprites and gameplay palettes now decode; original transfer/OAM and palette routines validate1,261pieces/6,730tiles. E320 adds a56-byte exact match. DBDC is sprite visibility/cache preparation, and FCE4 constructs OAM; the legacy RENDER_WORLD enum does not describe a recovered world renderer. World texture archives now decode666images/2,567,040bytes, with wholeAFF4/AF18, 65,539name comparisons and55,440 originalcolumn-copy blocks proving layout. Map wall bindings preserve live switch changes and pass1,059wholeB0C4calls; B0C4 matches54bytes exactly. Original ARM texturedcolumns pass67,678wholecalls, including7,992 usingall666loadedimages. Flatcolorfills andskycopy add6,189. The actual chain is02B88 ->B6B0 ->017CC ->BE60 ->ARM002F4; AB10/A98C handle flatcolor/skyplanes. Those geometry stages and the original actor passes now compose natively; HUD and final game integration remain. See world-scene.md and texture-assets.md, map-texture-bindings.md, world-raster.md and raster-fill.md. Sector+A/B arecolor/skyselectors,NOTtextureindices.

Original021E4 pause/menu orchestration is native with13,092wholeROMcomparisons, 60,101reentrychecks and41failureprefixes. UI command8EB0 andspritecreationE914 remainmandatoryevents. GameRuntime CONTROL still delegates toexternal; frontend mustbindcanonicalflags/sharedinput_state andimplementevents. See mode-control.md.

The H-toggle third-person camera extension is now implemented independently in src/view.c; see analysis/view.md. It computes a chase pose from recovered player/eye state, retracts against static geometry and preserves gameplay aim and movement. Native PC/Win32 event routing now handles H presses/repeats; the native viewer displays this chase pose and Sam's original animated body. H clears flag80 only in the rendering source snapshot, with gameplay flags preserved. Complete third-person game integration remains.

World geometry continuation:218,912visibility ROMcalls;14,322completeBE60solid/ portal calls;23,955plane routines. Connected B6B0/017CC/BE60/AB10 matches128 wholegeometry frames/all16maps/1,843,200pixels, withactorD2D0/01828excluded. 2,048PC/game/jump/Hframes add481,049sanitizerassertions and225guards while drawingactualgeometry. View routing02B88 adds84,032wholecalls/274,785native cameraassertions. B220 matches42bytes,A87024bytes;09238 adds32bytes andFB5C68. The catalogue nowcontains74exact/2152bytes=2.46%. The74-Cexport and independent rebuild are byte-identical. See world-visibility.md, wall-renderer.md, plane-renderer.md, render-view.md and world-scene.md.

Windowsviewer usesactualsingleplayerspawn/motion/collision/camera/jump directly, withoutdummyGameRuntime or gameplaycallbacks. Nativeclear/world events render 120x120worldindices,then240x160displaycomposition usingoriginalpalettes. Inputrawmouseforegoundonly, clickcapture,Esc/focus/menu/cancelrelease. 3,840hiddenWin32/GDIframes/all16maps and4CLI/ROMrejections pass; physical-device/visible-window interactionuntested. Original animated objects and the H body now render; combat,pickup execution, scripts,movers andaudio remain outside theviewer. Original normalHUD andidle startingweapon nowrender throughcache/OAM/240×160display; nofirecontrollerbound. Launchwith run-native-viewer.cmd [--level N]; see native-viewer.md.

Actor continuation:142resources/5407imagereferences/2607uniqueimages copy and decode natively. Whole09238/09258/ARM0638 sampling passes13787 original draw comparisons; ASan adds37860assertions. NativeD490/D884 projection andD2D0/D338 collection pass17664 isolatedcalls/256collections with9110emittedrecords. NativeF98/1238/01828 queue/depth/occlusion passes67840ROMcalls plus36564sanitizer assertions. Full originalB6B0 without actor hooks matches3686400pixels over 256views/all16maps, including128animatedframes,317actorcommands/2584walls. Only BIOSdivide/CpuSet/DMA are modeled at that boundary. See actor-assets.md, actor-projection.md, actor-queue.md and native-actor-scene-validation.json.

MapActors owns the385 original mapobjects, in01984allocation/world order, with 00908animation and no invented activation/AI state. All16maps/2048animation frames/49280originalrecords compare; owner lifecycle passes5404sanitizer assertions and preserves separately owned playerbodies onfree. Windowsviewer draws18326actorcommands,2762120changedactorpixels and1600visibleSamframes, using original65/66animation andD338overlay. The portable tests and Windows viewer exercise rendering independently of unfinished fullgame orchestration.

Normal sprite presentation now composes natively. The84-slot pool and101F4 constructor plus normalHUDcontrollers pass77424 whole-routine comparisons. FullFCE4/E648/FC3C/FC58 OAM passes6036calls/45603entries/10054affineobjects, with13183sanitizerassertions. Fullcache/visibility/allocator/transfer/reset adds 30596comparisons/7769920uploadedbytes/20624sanitizerassertions. The recovered mode1 display usesPA128/PD192 to sample the world at(x/2,floor3y/4) for240×160, withactualseparatepalettes andphysicalOBJ32Kmirror. Originalregister/map/tile setup passes448calls;635independentpixelframes coverall311realimages and128 affinecases,plus418281sanitizerassertions. Unsupportedblend/window/mosaic, mode4automap andpriority/budgetoverflow remain explicit errors.

The diagnosticHUDscene runs real1240Csetting0 before74HUDobjects,then12160 idleweaponraise,scalarHUDcontrollers,E460,DBDC,FCE4,E358andnativecomposition. Hhidesfirstpersonweaponwithoutchanginggameplayaim/body. Healthcomesfromspawned entity,armorfrominventory; score/time remaininitialized. Firing/combat arestill unbound rather than mocked. ActiveDnoticesexplicitlyunsupported. Windowsviewer passes3840frames/all16maps,3856HUDdraws/2112raisedfirstpersonweapondraws, 21807376changedpresentationpixels. Sourceandtestreports document boundaries.

ExactFB5C sprite-mark adds68bytes/34instructions,secondmanualcompile: live catalogue74/526,2152/87648bytes(2.46%),517attempts. FC3C83.9%(2attempts) and 074F0 83.2%(5attempts) areNOTexact. The74-Cexportrebuild isbyte-identical. See sprite-cache.md, sprite-oam.md, sprite-pool.md, display.md, hud-scene.md and currentvalidationJSON reports.

Historical checkpoint: first playable level — 15 October 2026

These are older development notes. See What you can play and Playable build details for what you can play today.

Playable level-one checkpoint, 2026-10-15

native_game.c and platform/win32/game.c now compose real simulation and rendering. The new play-native.cmd frontend exposes level0 only. The original viewer is retained separately. Normal difficulty, original loadout, live map objects, CD/CE/CF AI, real damage/firing, pickup inventory, wave/group gates, movers, exit detection and native PC restart all run. Space and H remain active. Audio is muted; original active text notices use simple host text.

The first-level bot uses only normal PC event APIs and read-only observations; its route planner changes only a private map copy. GCC ASan/UBSan/leak scanning and MSVC x64 both finish in5258 frames:28000score,8pickups,19spawned,100health, 13pistol/23shotgun shots. All16-map ownership proof adds4817checks. The existing game-runtime suite passes997410assertions/8220frames after shared pool changes. There are99Windowslibraries and three executables including the completion check.

Next work is remaining campaign/boss and special-weapon support, original UI, cross-level inventory carry, remaining palette/display effects and audio output. Do not claim the complete game is finished or expose unimplemented campaign paths as supported gameplay. The byte-matching catalogue remains separate from behavioral native coverage. See native-game.md and current validation reports.

Historical checkpoints: weapon corrections and campaign progression — 16 October 2026

These are older development notes. See What you can play and Playable build details for what you can play today.

Native weapon corrections, 2026-10-16

Local minigun/chainsaw/machinegun loop ownership now stops stale firing audio without cutting music or other sources. The PC game opts into launch-independent player rockets; the original recovery runtime retains its attachment quirk. The changed normal-input route exposed an offscreen portal row, now safely clipped with original sampling preserved. See weapon-fixes.md and current weapon-fixes-validation.json, windows-weapon-fixes-validation.json and campaign-validation.json. That checkpoint covered five campaign maps; current current campaign evidence is summarized above. These fixes add no matching catalogue entries.

The earlier110,468-frame consecutive run completed nine maps with earned carry. The sixth includes real D7 damage/death/projectiles/HUD/music and VM finish; the seventh completes in17,484frames. The eighth completes in15,023frames, ending at1,290,000score/78HP. The frontend admits indices0..8. The eighth adds both recessed switches, actual conversion frames and12,018,400 real-mixer stereo frames. The ninth completes in13,227frames with106spawns/14pickups, ending at 1,446,000score/53HP. It exercises original weapon9 acquisition and falling E3 effects,20conversion shots/12,991converted actor frames, both renderers and 10,581,600native stereo frames without decoder errors. The input bot waits18 frames clear of an original closing-door hazard, reverses wall-blocked strafes, and uses jumping and its earned special weapons. Only the admission count and normal-input test planner changed; no game collision, hazard or inventory bypass. The bot's cardinal escape steps, ranged spacing and supply strafing are normal PC input; game collision, enemy health, damage and script rules are unchanged. This proof uses the current original minigun cadence, firing-animation weapon handoff and immediate E-button policy, superseding older timing checkpoints. Boss/post-boss audio loops now use gameplay music2/19/20; focused126730assertions pass. Later D8 natural progression, interchapter presentation and original feature parity remain unfinished. See enemy-boss.md and current campaign reports.

Sprite floor clipping (2026-10-21)

Software/Vulkan now use the recovered GBA wall-silhouette rules for actors, including death/explosion artwork crossing its floor. Shared clipping operates before pitch and reflection transforms; nearer solid walls and portal bounds still hide actors. GBA remains unchanged. See sprite-clipping.md for implementation and focused regression results.

Floor/ceiling edge decals (2026-10-21)

Surface decals now includes randomly placed, connected grime strips at dry floor and ceiling boundaries. An8KiB stored binary atlas uses the existing surface palette and2-unit texels, with matching ports and empty/end variants. All renderers share the live boundary sampler and existing shoreline index. See surface-decals.md for ownership and validation.