03 · Every step
Step by step: twenty-four days, then forty-three more, then one week
Five chapters, one per tab: the New 3DS port (five bursts between three credit pauses), the native fork, the Old 3DS, shipping v1.0.0, and the week after it. Dates are local, from git and the session transcripts; quotes are the user's own words at the time.
Every entry was re-checked against what came after it. Where later evidence revised a number, a root cause or a decision, the entry carries a numbered Later note; Held marks a claim that was checked and stands.
Burst 1 · Research to first race (08-11 → 08-14)
- 08-11 03:16Deep research: is a 3DS port feasible?24 Verdict: New 3DS only; the Old 3DS 64 MB region cannot hold it.Later (09-25 → 10-19): it fit under simulation on 09-25, booted on an Old 3DS on 09-29, and shipped for the Old 3DS in v1.0.0. — this page, chapter 3; RELEASE-NOTES.md v1.0.0
- 08-11 03:44Plan for a team of agents "can we segment plan so we can have multiple work trees and multiple contributing agents ?" A memory budget, a five-stream plan and a reviewer agent.
- 08-11 → 08-12Phase 0 and the carve spike libultraship compiles on devkitARM with a 13-line newlib patch; Phase 1 streams merged 08-12 21:45.
- 08-13"start the crew", then black screens Full game linked 01:33; then bzero, 64DD, path mangling, double swap, the SETTIMG guard, a DMA misroute. 13:17: "i saw some random shapes briefly".
- 08-14 01:01First race "omg it works ! i can race ! it looks messed up and runs at 12 to 20fps but it works!" (after a race-time bad_alloc fix).
- 08-14 04:26Hardware prep, CI, docs CIA packaging, a hardware runbook, local CI; research on 60 fps and on stereo 3D.
- 08-14 14:06Pause 1 "we ran out of fable credits until next week". Fog (pink road) still open.
Burst 2 · Playable, then hardware (08-20 → 08-22)
- 08-20 02:55Resume; the road appears Fog solved (per-vertex blend, not the depth LUT); fog, GPU profiling, stereo, perf and culling merged.
- 08-20 05:38"run as many subagents on plausible tasks"23 A fleet on HUD, shadow, sky, tunnel, km/h, pop-in. The measurement pass: CPU-bound, not GPU-bound.Held (09-01 → 10-24): an emulator measurement at the time (GPU 0.4 ms vs CPU 26–58 ms); hardware agreed (GPU 5.6 vs build 16.3 ms), and the Old 3DS probe agreed on 10-24. — locked60-campaign.md; NATIVE-RENDERER.md ceiling_probe
- 08-20 22:45The HUD bug After eight wrong fixes: the bridge's ILP32 high-bits backstop dropped 13 SETTIMG a frame. "omg finally!!"
- 08-21 13:03"menus … still crazy slow at around 10fps" A per-opcode profiler named G_LOADBLOCK at 22.34 ms a frame; fixed within the hour. "blazing fast on the UI".
- 08-21 15:54First hardware run "wow it runs amazing ! … sound doesn't work btw". Audio fixed by 21:22 after eleven SD trips (the ROM-side driver needed host porting).
- 08-21 22:49"framerate at a crispy 60. then... maybe 3D?" Race-start hitch and decal fixes. Hardware median 48–50 fps, p95 58.
- 08-22 01:31Pause 2 "ran out of tokens again". Checkpoint 854b9d6.
Burst 3 · Product grade (08-27 → 08-28)
- 08-27 06:21Fleet drop Traffic grind (bridge 19.7 → 10.4 ms), sky wedge, CCMUX 11, off-axis stereo, shadow audit.
- 08-27 16:00Hardware with stereo22 "3D works great, doesnt seem to affect performance much"; first hard crash: the filelog grew without bound, fixed with a retained ring.Later (09-02 → 10-02): the 256 KB cap truncated a session (raised to 1 MB, 09-02); the ring then caused 26–270 ms and 1.1–2.8 s SD-write hitches (09-30), fixed by an async, dropping writer. — 2344e88; difficulties.html
- 08-27 16:53Touch menu and full bleed "the bottom screen should have a menu for these features"; full-bleed made default. 19:30: "i did the first GP!"
- 08-28 00:18Rival detail, packed VBO, HOME exit21 "minimal appears to be a 8 to 9 fps gain !"Later (10-19): the New 3DS preset runs full rival detail; automatic scaling is used on the Old 3DS. — gdx3ds_preset_n60.c; RELEASE-NOTES.md v1.0.0
- 08-28 04:27"moonshot! lets go for it"20 GPU vertex transform in one session: works, imperceptible on hardware, breaks the venue floor. Shelved.Later (09-29): the broken floor was traced to float24 cancellation on world-space vertices (up to ±32,000); a machines-only transform was rebuilt for the Old 3DS and ships in both presets. — o3dsgpuxf-progress.md; gdx3ds_preset_n60.c
- 08-28 13:17README and pause 3 README-3DS and the release package. Then the third pause.
Burst 4 · The last big lever (09-01 → 09-02)
- 09-01 21:27"the goal to 60fps"19 Bridge output cache NO-GO (87% of commands are host-built each frame); brfast memos instead, bridge 11.5 → 4.9 ms. Research: nobody has shipped beyond the per-frame walk.Later (10-02): the native race renderer (10-01/02) skips building the game's display-list sections on rendered ticks and draws from GPU-resident meshes. — native.html
- 09-01 23:53"the home button crashes the game!" Suspend-path audit and audio park gate; the first combined A/B test card.
- 09-02 14:02Hardware round 2 HOME works; close-from-HOME hang fixed. brfast: median 57.2 vs 56.0, p10 47.2 vs 42.0.
- 09-02 14:41LOCKED-60 campaign HUD atlas, TMEM bookkeeping, per-triangle cost, boot audio: four agents, landed by 13:40.
- 09-02 18:35"VERY slow. massive step back" A combined-lever HUD break; fixed, and "screenshot the combined levers before staging" became a rule.
- 09-02 21:56Rounds 3 and 4 Median 56, p10 48, 32% at the cap with stereo on; trace-on A/B steady 16.4 → 14.9 ms.
- 09-02 21:59Research 218 Core 2 usable, core 3 not, no precedent for cross-core render pipelining. Agents on a dispatch census, boot audio, a render thread.Later (10-19): the render thread shipped in v0.9.0 and was left out of the v1.0.0 presets (above). — gdx3ds_preset_n60.c
Burst 5 · Multi-core (09-02 night → 09-03)
- 09-02 → 09-03Render thread, sync → pipe → ahead Forked at osSpTaskStartGo; ahead mode acks DP-done when the game parks. Pipe mode on hardware: median 49 → 56.
- 09-03 13:20Round 5: median 59.6, p10 51.4, 53% at the cap17 Ahead mode, bridge on main, auto rival detail. Then a hard crash (texture-cache LRU on core 2), fixed by render-thread ownership.Later (10-19 → 10-26): v1.0.0's tuned presets set
renderthread = 0: the native race path fits 16.7 ms on one core. Card 6: New 3DS 3D races at 60 in every window without it. — gdx3ds_preset_n60.c; o3ds-card6-analysis.md §4 - 09-03 13:46 → 16:32Menu scale and stereo markers Machine-select 1.6× too large (viewport fold); 1P/2P markers anchored at the ship's depth.
- 09-03 18:08This post-mortem "lets write up a whole post mortem on this project."
- 09-04State of play (v0.9.0)16 Ahead mode, bridge-on-main, auto rival detail and the crash fixes all merged. The GPU vertex transform stayed shelved; the tunnel-roof bug (#27) was still open at v1.0.0.Later (09-29 → 10-19): a machines-only
gpuxf = 1(the floor stays on the CPU) is on in both consoles' auto presets in v1.0.0 and v1.1.0. — gdx3ds_preset_n60.c; o3dsgpuxf-progress.md
A feasibility pass on 09-07 found the fix should start with the development loop, not the renderer: no network path to the console, no frame oracle, no desktop reference build. Over two weeks that loop was rebuilt (a network control and log link, input-recorder determinism, a Linux reference render container), and the first renderer tier landed: an owned F3DEX2 interpreter replacing libultraship's, a native race path (track, machines, sky, HUD, effects), and the first 64DD Expansion Kit pass. In full on The road to 60, all over again.
- 09-24The milestone reopens A stale note said the user owned no Old 3DS; they did. Under a simulated 64 MB grant: RDRAM arena halved to 8 MiB,
audio_tablestreamed. - 09-25It fits, in simulation15 Replay 49/49 under
memtype=0with 2.65 MiB to spare.Later (10-16 → 10-26): a 10-16 hardware capture peaked at heapUsed ≈ 24.2 MB; card 6 logged a race watchdog at heapFree=3264. — STATUS.md; o3ds-card6-analysis.md §5.1 - 09-28The console says
memtype=0Matches the simulation byte for byte; the shipped RDRAM-16 build dies in its boot preload. - 09-29 00:10"it ran ! at like 9fps" Wall p50 96 ms, GPU busy 3.6 ms. "is there anything we can do to avoid the display lists"
- 09-29 dayThe parallel wave Audio-lock wait 25.8 → 0.2 ms, the HOME freeze (backlight session), bit-exact ARMv6 SIMD audio, the slow-motion discovery.
- 09-29 13:09"we want this running at 60fps" A design sub-orchestrator and five research and probe subagents.
- 09-29 15:16"playable but nausea inducing"14 Frame skipping: logic 57–60 ticks/s, drawn 19–28 fps. Draw cost measured at 10.9 µs per draw.Held (10-26): DrawProbe measured 10.9 µs flat over 30–300 draws (2,926 cycles). A uniform-free draw is 8.0 µs; a trimmed citro3d reached ~6.8 µs in the emulator, unmeasured on hardware; race draws now bypass it. — cpu-profile-answer.md §A.2
- 09-29 19:39First release candidate does not boot13 Cold size-optimised code crashes, stock boots; code generation reverted. The latent bug was never found.Held (10-26): still unproven; code generation stays stock and hot-first ordering was never re-tested on hardware. — rel1crash-progress.md; agent-D-cpu-cuts.md
- 09-30 01:10Second candidate boots, hitching12 "like 15fps ... a lot of awkward hitching": synchronous SD log flushes, 26–270 ms on main.Later (10-02 → 10-19): a full ring later forced 1.1–2.8 s writes; fixed by an async writer, then a log that drops lines rather than block. v1.0.0's own figure still shows the gap (57.3 vs 51.9 fps). — difficulties.html; RELEASE-NOTES.md v1.0.0
- 09-30 02:09"start as many agents as necessary" Seven agents hit the session limit together and were resumed; then the disk filled.
- 09-30 → 10-01A hardware profiler11 CPI 4.34, 43.6% fetch stalls; a probe found the cliff from CPI 1.06 at 16 KB of hot code to 4.1 at 24 KB.Held (10-07 → 10-08): native-renderer builds cut instructions ~3.6× and I-misses ~4×, but CPI rose to 5.4–6.4 with I-fetch stalls at 28–32%: less code, not faster code. — cpu-profile-answer.md §A.3
- 10-01 08:57"we should go for a real 60!" Pose replay (40 images/s, artifacts) set aside against a research verdict of "marginal"; an I-cache-first native race renderer begins.
- 10-01 22:41First native-renderer build freezes A verify mode rolled back the live GPU command queue; hardware only.
- 10-02 09:28"time trial was silk 60fps" 199,472 draws verified, 0 bad; Grand Prix 45–50 with log hitches. Saves after the first never persisted (fixed).
- 10-02 23:19"omg it ran amazing!" Card 3: race median 16.5 ms, 0 hitches. "lets focus on 3D at 60fps".
- 10-033D, first pass10 Black sky on an interim build, then "60fps for 2d for both", 3D in the 40s and 50s. The right eye is interleaved per chunk.Later (10-26): each chunk's two eyes became one queue entry (CMDBUF_JUMP): Old 3DS race entries 9 → 7, 3D menus 40.2 → 44.6 fps; v1.1.0 default. — ba0692e; a2905ed
- 10-03 → 10-07Rate-limit pause One branch's uncommitted edits recovered on 10-07.
- 10-07 22:513D, second pass Mute City ~60 in 3D with end-mode pacing; heavier venues 16–18 ms.
- 10-08 02:08"all 3 crashed" Bottom-screen framebuffer in VRAM, which a CIA maps read-only for the CPU; the emulator does not enforce it.
- 10-08 02:56"did a long play on main, was good!"9 VRAM change reverted: 3D Grand Prix race windows at 59–60 fps; 0 bad draws.Later (10-24 → 10-26): a development card, not the shipped build. A 16-machine race later ran 53.7 fps; one submission brought the 1P race to 59.7–59.8. — cpu-profile-answer.md §A.4; o3ds-card6-analysis.md
- 10-08Card 4 closes the 3D push8 59–60 fps in 3D Grand Prix race windows on a development card; the rest of v1.0.0 followed. Commit- and document-sourced from here.Later (10-19 → 10-26): v1.0.0 shipped 3D as “not yet a locked 60 fps”; a heavier 16-machine 1P race measured 53.7 fps (10-24); card 6's baseline ran 56.4 / 59.3 and one submission 59.7–59.8 (10-26). — RELEASE-NOTES.md; cpu-profile-answer.md §A.4
- 10-07 → 10-08Expansion Kit: own title and save The last blocker to a second, side-by-side install.
- 10-08 → 10-15Rate-limit pause The longest gap of the project.
- 10-15 → 10-17The bottom screen becomes DASH7 Lap, position, energy, splits, composited into the framebuffer at well under a millisecond of CPU time.Later (10-23): on Old 3DS hardware the DASH cost 4.2–5.6 ms a frame and was put on a 1 ms budget. — d9deb37; e99777b
- 10-16The Old 3DS memory ceiling, in simulation6 One large mid-race asset load can exhaust the budget (the generic archive loader); a hardware capture peaked near 24.2 MB. Left as a known limit.Later (10-26): v1.1.0 moved ~320 KB off the main heap and reserved the track at boot; card 6 showed the failure mode is fragmentation. Tight memory stays a known issue. — d7010a8; a2905ed; RELEASE-NOTES.md v1.1.0
- 10-16An audio-crackle hypothesis, refuted5 Vblank vs audio rate measured and ruled out; a smaller resample fix ships.Held (10-20): v1.1.0 turns the clamp and declick fixes on for the New 3DS, not yet confirmed to cure its crackle; Old 3DS residual crackle still open. — RELEASE-NOTES.md v1.1.0 Audio; 9ead784
- 10-18A New 3DS froze at the title screen The attract demo's full-field race overflowed the GPU command buffer; see The road to 60, all over again.
- 10-18 → 10-19Custom HUD mode shelved The three fixed DASH layouts ship; an idle view outside races.
- 10-19Disk streaming and Japanese inputs by default The 64DD image streams from SD on every build; Japan-region inputs accepted.
- 10-19v1.0.0 Four build targets from one tree, three downloads (Old 3DS, New 3DS, New 3DS + Expansion Kit; the Old 3DS Kit build stays from-source), replacing the New-3DS-only v0.9.0.
- 10-20 → 10-25Multiplayer Local wireless, same-Wi-Fi and online rooms, lockstep races with each console showing its own racer, a relay server, version gating. Old 3DS: 2D 60 in a 16-racer online race; 3D locked to 30. See MULTIPLAYER.md.
- 10-24The Old 3DS 3D ceiling probe4 Waiting out the previous frame's GPU work first made the frame no cheaper (13.5 → 14.2 ms), so a deferred-wait redesign was dropped: 3D races here are CPU-bound.Later (10-26): card 6 found 3D menus waiting 7.66 ms a frame on the GPU queue (per-entry latency); one submission per stereo chunk took them from 40.2 to 44.6 fps. — o3ds-card6-analysis.md §3
- 10-26HOME close, fixed3 Card 5's Old 3DS hard lock was a 73 KB allocation in the 64DD save flush; the flush now allocates nothing.Later (10-26): while chasing this lock a 617 KB drop in free heap was reported as a regression. The two logs compared were a 2D multiplayer session and a 1P 3D session; the comparison was wrong, not the build. — o3ds-card6-analysis.md; 9d19a5c
- 10-26One submission for both eyes2 From a homebrew developer's public question. Card 6 A/B: Old 3DS 3D menu 40.2 → 44.6 fps, race GX entries 9 → 7, 1.5–1.8 ms of headroom; New 3DS neutral. v1.1.0 default.Held (10-26): the menu result (6 vs 9 blocks, ±0.2 fps) is solid; the race figure rests on two blocks per arm. The Old 3DS frame has 9 queue entries, not the 11 the pre-card notes assumed. — onesubmit-progress.md; o3ds-card6-analysis.md §0
- 10-26Track arena and a wider 3D sky1 The course track moves into one 777,360-byte arena reserved at boot, aimed at the fragmentation failure card 6 hit; sky, floor and clouds widened by the eye shift.Later (10-26): built for card 6's failure (a 96,768-byte allocation refused with 1.6 MB free: fragmentation, not exhaustion); tested in the emulator, not yet on hardware. — RELEASE-NOTES.md v1.1.0 known issues; o3ds-card6-analysis.md §5.1
- 10-26The bottom screen, last pass DASH layout, D-pad navigation in the multiplayer sheets, one SETTINGS button.
- 10-26v1.1.0, prepared for release This page's last entry.