Dit artikel is een post-mortem van het project om G-Diffuser, een decompilatie van F-Zero X, naar de Nintendo 3DS te porteren. Het project verliep in twee fasen: de eerste fase richtte zich op het behalen van 60 fps in 3D op de New 3DS, terwijl de tweede fase ondersteuning toevoegde voor de Old 3DS, een native renderer en de 64DD Expansion Kit.
Belangrijke technische en operationele details:
- Ontwikkeling: Het project werd geleid door één persoon met intensieve ondersteuning van AI (Claude), waarbij miljarden tokens werden verbruikt tegen aanzienlijke kosten.
- Prestaties: Op de New 3DS werd een gemiddelde framerate van 59,6 fps bereikt. Voor de Old 3DS werd een native renderer ontwikkeld die specifiek is geoptimaliseerd voor de instruction-cache, waardoor ook op dit platform hoge framerates mogelijk zijn.
- Technische Stack: Er is gebruikgemaakt van de
inspectredc/fzerox decompilatie, de Kenix3 N64 runtime en een citro3d rendering backend.
- Resultaat: Er zijn drie verschillende builds uitgebracht (Old 3DS, New 3DS en New 3DS met Expansion Kit) die volledige game-functionaliteit bieden, inclusief stereoscopische 3D en een dashboard op het onderste scherm.
G-Diffuser op 3DS
Het project werd geleid door één persoon en gecoördineerd via één langlopende Claude-sessie, waarbij 147 subagents de eerste fase bouwden en nog veel meer agents betrokken waren bij de tweede fase.
De console evolueerde van een zwart scherm naar een native-60 stereoscopische racer, en van een build die alleen op de New 3DS werkte naar een release met vier varianten die beide consoles ondersteunen, met en zonder de 64DD-expansie.
Belangrijkste statistieken (Fase 1)
Prestaties op hardware (New 3DS):
- Gemiddelde framerate: 59,6 fps (gemeten tijdens een volledige Grand Prix aan het einde van de eerste fase; gestegen van 12–20 fps in de eerste emulator-race).
- Ondergrens (10e percentiel): 51,4 fps in groepen van 30 machines (gestegen van 25–35 fps).
- Frames op de 60 fps cap: 53% (gestegen van 14% één week eerder).
Ontwikkeling en kosten:
- Actieve dagen: 15 dagen verspreid over de 24 kalenderdagen van de eerste fase (met drie pauzes wanneer het wekelijkse budget voor het plan was opgebruikt).
- Tokens: 3,17 miljard tokens over alle sessies en agents (alleen eerste fase).
- Kosten: $4.974 op basis van gepubliceerde API-lijstprijzen (Fable $10/$50 per MTok, 1-uur cache writes), alleen eerste fase.
- Commits: 250 commits die de 3DS-port raakten in de eerste fase (bevroren op 08-10-2026 op basis van de v0.9.0 documentatie).
- Code: 15.039 regels onder
port/3ds plus 48 pure-delta patches (aantal uit de eerste fase).
Toevoegingen in v1.0.0
- Console-builds: Drie released builds vanuit één bronboom: Old 3DS, New 3DS, en New 3DS met de Expansion Kit.
- Documentatie: 199 interne voortgangsnotities geschreven tijdens de tweede fase.
- Tijdsbestek: Een kalenderperiode van 43 dagen voor de tweede fase (07-09-2026 tot 19-10-2026).
Opmerking: De hardwarecijfers, token- en kostengegevens van de eerste fase zijn gemeten tot 03-09-2026 en zijn niet opnieuw uitgevoerd voor v1.0.0.
Wat er is gebouwd
Er zijn drie console-builds uitgebracht vanuit één bronboom, die allemaal kunnen opstarten via het HOME-menu (.cia) of de homebrew launcher (.3dsx):
- De basisgame voor Old 3DS / 2DS.
- De basisgame voor New 3DS / New 2DS XL.
- Een New 3DS-build met de 64DD Expansion Kit (inclusief course editor en machine creator, speelbaar met een door de gebruiker geleverd disk-image).
Elke build leest vooraf gebakken asset-archieven van de SD-kaart; er wordt nooit een ROM of disk-image meegeleverd met het spel.
De port bevat de volledige game: Grand Prix, Time Trial, Practice, Death Race en de machine-editor schermen. Muziek en effecten draaien op de echte DSP, stereoscopische 3D is beschikbaar via de slider, en er is een dashboard op het onderste scherm met drie HUD-layouts en een ruststand buiten de races. De software ondersteunt clean HOME-suspend, resume, sluiten, inklappen van het scherm en uitschakelen.
De New 3DS-build behoudt de native-60 frame pacing die in de eerste fase is bereikt. De Old 3DS-build bereikt een vergelijkbaar resultaat via een andere route. In v1.0.0 gebruiken beide builds standaard de native renderer ([perf] preset = auto). De render-thread/per-draw-stereo route van de New 3DS uit de eerste fase is nog steeds aanwezig en bereikbaar via een expliciete .ini, maar is niet langer de standaard.
De technische stack
- Decomp: De F-Zero X decompilatie (
inspectredc/fzerox), ongewijzigd upstream, plus een stack van patches.
- libultraship: De N64 runtime (
Kenix3), ongewijzigd upstream, inclusief een newlib-fix van 13 regels waardoor het kan bouwen op devkitARM. Dit onderdeel tekent alle menu's en schermen buiten de races.
- port/3ds: 15.039 regels (stand fase 1), later uitgebreid. Bevat een citro3d rendering backend, stereo, audio, input, menu, lifecycle, render thread, profilers en packaging.
- Native renderer (toegevoegd in fase 2): Een eigen interpreter die de per-frame display-list loop voor race-geometrie overslaat. Dit is de standaard in v1.0.0 voor beide consoles en is wat de Old 3DS in staat stelt om bij te blijven.
Prestaties op hardware (Fase 1 - New 3DS)
| Datum | Scenario | Mediaan | p10 | At cap (60fps) |
| 14-08 | Eerste race (emulator) | 12–20 | – | – |
| 21-08 | Eerste hardware run | 48–50 | – | – |
| 28-08 | Release-grade build | ~51 | ~40 (crowds, MINIMAL) | – |
| 02-09 (R1) | Mainline voor de campagne | 51.3 | 39.2 | 9% |
| 02-09 (R2) | Bridge memos (brfast) | 57.2 | 46.6 | 29% |
| 02-09 (R3) | HUD atlas, triangle memo, TMEM, audio | 56.0 | 48.0 | 32% |
| 02-09 (R4) | Render thread op core 2 (pipe) | 57.6 | 44.6 | 14% |
| 03-09 (R5) | Ahead mode, bridge on main, auto rival detail | 59.6 | 51.4 | 53% |
Chronologie Fase 1
- 11-08 → 14-08: Van onderzoek naar de eerste race. Opstellen van feasibility dossier, plan voor een team van agents, vijf parallelle foundation-streams, oplossen van zes boot-bugs. Eerste race op 12–20 fps in de emulator.
- 20-08 → 22-08: Van 'pink' naar speelbaar, en daarna naar een echte console. Fog, HUD, livery, shadow en sky hersteld; ontdekking van de loadblock bracht menu's van 27 naar 60 fps. Eerste hardware run op 21-08; audio toegevoegd diezelfde avond.
- 27-08 → 28-08: Product-grade. Inzet van een fleet van vijf agents, stereo geactiveerd, touch menu, rival detail. Een GPU vertex-transform 'moonshot' is gebouwd maar geparkeerd. README met juridische kennisgeving en release-pakket voltooid.
- 01-09 → 02-09: Lifecycle en de laatste grote optimalisatie. HOME-crash en close-from-HOME hang opgelost. Een bridge output cache bleek niet te werken en werd vervangen door het memoizen van de classificatie van elke sub-display-list. Start van de LOCKED-60 campagne met vier parallelle methoden.
- 02-09 → 03-09: Multi-core. Render thread op core 2, one-frame-ahead mode, bridge on main, auto LOD. Resultaat: mediaan 59,6 fps met 53% van de frames op de cap. Crash opgelost, viewport-plaatsing hersteld en stereo markers verankerd.
Chronologie Fase 2
Deze fase was oorspronkelijk niet gepland en liep van 07-09 tot 19-10 (43 kalenderdagen).
- 07-09 → 29-09: Scoping en optimalisatie. De mijlpaal voor de Old 3DS werd herstart. Parallelle agents pasten de build aan de 64 MB app-regio aan (RDRAM arena gehalveerd, audio gestreamd in plaats van resident, texture uploads beperkt). Op 29-09 bootte de specifieke Old 3DS-profiel build en draaide deze op ongeveer 10 fps.
- 29-09 → 30-09: Analyse van de werkelijke kosten. Een versmalde audio-lock verminderde de race-wall wait op de Old 3DS met ongeveer 20 ms per frame. Frame skipping maakte een einde aan de accidentele slow-motion. Een eerste retained-mode renderer leverde grote winst op in de emulator, maar nauwelijks op hardware.
- 30-09 → 01-10: De ontdekking die het plan veranderde. Hardware-performance counters toonden aan dat de werkelijke limiet instruction-cache misses waren, niet het aantal instructies. Een pose-replay fallback werd gebouwd, maar later geparkeerd omdat het doel een "echte 60 fps" moest zijn.
- 01-10 → 02-10: De native renderer. Deze werd herbouwd rond de cache in plaats van rond instructie-aantallen, met één kleine loop per race-categorie, precies passend in de 16 KB instruction cache. De mediane frametime voor een 2D Grand Prix race bereikte 16,5 ms.
- 03-10 → 08-10: 3D op 60 fps, ook op de Old 3DS. Een per-eye resubmit met een eigen swap-pacing mode bereikte 59–60 fps in 3D op de meeste Grand Prix-courses. De zwaarste courses (Silence, Sand Ocean) kunnen nog steeds terugvallen op een stabiele 30 fps via het frame-skip vangnet.
- 08-10 → 19-10: De Expansion Kit, dashboard en release. De 64DD Expansion Kit werd geverifieerd als tick-for-tick identiek onder de native renderer en bootte op de Old 3DS (hoewel deze te traag bleek voor release op dat platform). Het DASH-scherm voor het onderste scherm werd toegevoegd. Een laatste adversarial review controleerde het resultaat voor de v1.0.0 release.
Bronnen
Alle cijfers in dit document zijn gebaseerd op:
- Git-geschiedenis.
- Onderzoeksdocumenten in
docs/research/.
- Hardware-logs.
- Sessie-transcripten.
- Schattingen (zoals dollar-bedragen) zijn gebaseerd op gepubliceerde API-lijstprijzen toegepast op exacte token-aantallen.
G-Diffuser op 3DS
Het project werd geleid door één persoon en gecoördineerd via één langlopende Claude-sessie, waarbij 147 subagents de eerste fase bouwden en nog veel meer agents betrokken waren bij de tweede fase.
De console evolueerde van een zwart scherm naar een native-60 stereoscopische racer, en van een build die alleen op de New 3DS werkte naar een release met vier varianten die beide consoles ondersteunen, met en zonder de 64DD-expansie.
Belangrijkste statistieken (Fase 1)
Prestaties op hardware (New 3DS):
- Gemiddelde framerate: 59,6 fps (gemeten tijdens een volledige Grand Prix aan het einde van de eerste fase; gestegen van 12–20 fps in de eerste emulator-race).
- Ondergrens (10e percentiel): 51,4 fps in groepen van 30 machines (gestegen van 25–35 fps).
- Frames op de 60 fps cap: 53% (gestegen van 14% één week eerder).
Ontwikkeling en kosten:
- Actieve dagen: 15 dagen verspreid over de 24 kalenderdagen van de eerste fase (met drie pauzes wanneer het wekelijkse budget voor het plan was opgebruikt).
- Tokens: 3,17 miljard tokens over alle sessies en agents (alleen eerste fase).
- Kosten: $4.974 op basis van gepubliceerde API-lijstprijzen (Fable $10/$50 per MTok, 1-uur cache writes), alleen eerste fase.
- Commits: 250 commits die de 3DS-port raakten in de eerste fase (bevroren op 08-10-2026 op basis van de v0.9.0 documentatie).
- Code: 15.039 regels onder
port/3ds plus 48 pure-delta patches (aantal uit de eerste fase).
Toevoegingen in v1.0.0
- Console-builds: Drie released builds vanuit één bronboom: Old 3DS, New 3DS, en New 3DS met de Expansion Kit.
- Documentatie: 199 interne voortgangsnotities geschreven tijdens de tweede fase.
- Tijdsbestek: Een kalenderperiode van 43 dagen voor de tweede fase (07-09-2026 tot 19-10-2026).
Opmerking: De hardwarecijfers, token- en kostengegevens van de eerste fase zijn gemeten tot 03-09-2026 en zijn niet opnieuw uitgevoerd voor v1.0.0.
Wat er is gebouwd
Er zijn drie console-builds uitgebracht vanuit één bronboom, die allemaal kunnen opstarten via het HOME-menu (.cia) of de homebrew launcher (.3dsx):
- De basisgame voor Old 3DS / 2DS.
- De basisgame voor New 3DS / New 2DS XL.
- Een New 3DS-build met de 64DD Expansion Kit (inclusief course editor en machine creator, speelbaar met een door de gebruiker geleverd disk-image).
Elke build leest vooraf gebakken asset-archieven van de SD-kaart; er wordt nooit een ROM of disk-image meegeleverd met het spel.
De port bevat de volledige game: Grand Prix, Time Trial, Practice, Death Race en de machine-editor schermen. Muziek en effecten draaien op de echte DSP, stereoscopische 3D is beschikbaar via de slider, en er is een dashboard op het onderste scherm met drie HUD-layouts en een ruststand buiten de races. De software ondersteunt clean HOME-suspend, resume, sluiten, inklappen van het scherm en uitschakelen.
De New 3DS-build behoudt de native-60 frame pacing die in de eerste fase is bereikt. De Old 3DS-build bereikt een vergelijkbaar resultaat via een andere route. In v1.0.0 gebruiken beide builds standaard de native renderer ([perf] preset = auto). De render-thread/per-draw-stereo route van de New 3DS uit de eerste fase is nog steeds aanwezig en bereikbaar via een expliciete .ini, maar is niet langer de standaard.
De technische stack
- Decomp: De F-Zero X decompilatie (
inspectredc/fzerox), ongewijzigd upstream, plus een stack van patches.
- libultraship: De N64 runtime (
Kenix3), ongewijzigd upstream, inclusief een newlib-fix van 13 regels waardoor het kan bouwen op devkitARM. Dit onderdeel tekent alle menu's en schermen buiten de races.
- port/3ds: 15.039 regels (stand fase 1), later uitgebreid. Bevat een citro3d rendering backend, stereo, audio, input, menu, lifecycle, render thread, profilers en packaging.
- Native renderer (toegevoegd in fase 2): Een eigen interpreter die de per-frame display-list loop voor race-geometrie overslaat. Dit is de standaard in v1.0.0 voor beide consoles en is wat de Old 3DS in staat stelt om bij te blijven.
Prestaties op hardware (Fase 1 - New 3DS)
| Datum | Scenario | Mediaan | p10 | At cap (60fps) |
| 14-08 | Eerste race (emulator) | 12–20 | – | – |
| 21-08 | Eerste hardware run | 48–50 | – | – |
| 28-08 | Release-grade build | ~51 | ~40 (crowds, MINIMAL) | – |
| 02-09 (R1) | Mainline voor de campagne | 51.3 | 39.2 | 9% |
| 02-09 (R2) | Bridge memos (brfast) | 57.2 | 46.6 | 29% |
| 02-09 (R3) | HUD atlas, triangle memo, TMEM, audio | 56.0 | 48.0 | 32% |
| 02-09 (R4) | Render thread op core 2 (pipe) | 57.6 | 44.6 | 14% |
| 03-09 (R5) | Ahead mode, bridge on main, auto rival detail | 59.6 | 51.4 | 53% |
Chronologie Fase 1
- 11-08 → 14-08: Van onderzoek naar de eerste race. Opstellen van feasibility dossier, plan voor een team van agents, vijf parallelle foundation-streams, oplossen van zes boot-bugs. Eerste race op 12–20 fps in de emulator.
- 20-08 → 22-08: Van 'pink' naar speelbaar, en daarna naar een echte console. Fog, HUD, livery, shadow en sky hersteld; ontdekking van de loadblock bracht menu's van 27 naar 60 fps. Eerste hardware run op 21-08; audio toegevoegd diezelfde avond.
- 27-08 → 28-08: Product-grade. Inzet van een fleet van vijf agents, stereo geactiveerd, touch menu, rival detail. Een GPU vertex-transform 'moonshot' is gebouwd maar geparkeerd. README met juridische kennisgeving en release-pakket voltooid.
- 01-09 → 02-09: Lifecycle en de laatste grote optimalisatie. HOME-crash en close-from-HOME hang opgelost. Een bridge output cache bleek niet te werken en werd vervangen door het memoizen van de classificatie van elke sub-display-list. Start van de LOCKED-60 campagne met vier parallelle methoden.
- 02-09 → 03-09: Multi-core. Render thread op core 2, one-frame-ahead mode, bridge on main, auto LOD. Resultaat: mediaan 59,6 fps met 53% van de frames op de cap. Crash opgelost, viewport-plaatsing hersteld en stereo markers verankerd.
Chronologie Fase 2
Deze fase was oorspronkelijk niet gepland en liep van 07-09 tot 19-10 (43 kalenderdagen).
- 07-09 → 29-09: Scoping en optimalisatie. De mijlpaal voor de Old 3DS werd herstart. Parallelle agents pasten de build aan de 64 MB app-regio aan (RDRAM arena gehalveerd, audio gestreamd in plaats van resident, texture uploads beperkt). Op 29-09 bootte de specifieke Old 3DS-profiel build en draaide deze op ongeveer 10 fps.
- 29-09 → 30-09: Analyse van de werkelijke kosten. Een versmalde audio-lock verminderde de race-wall wait op de Old 3DS met ongeveer 20 ms per frame. Frame skipping maakte een einde aan de accidentele slow-motion. Een eerste retained-mode renderer leverde grote winst op in de emulator, maar nauwelijks op hardware.
- 30-09 → 01-10: De ontdekking die het plan veranderde. Hardware-performance counters toonden aan dat de werkelijke limiet instruction-cache misses waren, niet het aantal instructies. Een pose-replay fallback werd gebouwd, maar later geparkeerd omdat het doel een "echte 60 fps" moest zijn.
- 01-10 → 02-10: De native renderer. Deze werd herbouwd rond de cache in plaats van rond instructie-aantallen, met één kleine loop per race-categorie, precies passend in de 16 KB instruction cache. De mediane frametime voor een 2D Grand Prix race bereikte 16,5 ms.
- 03-10 → 08-10: 3D op 60 fps, ook op de Old 3DS. Een per-eye resubmit met een eigen swap-pacing mode bereikte 59–60 fps in 3D op de meeste Grand Prix-courses. De zwaarste courses (Silence, Sand Ocean) kunnen nog steeds terugvallen op een stabiele 30 fps via het frame-skip vangnet.
- 08-10 → 19-10: De Expansion Kit, dashboard en release. De 64DD Expansion Kit werd geverifieerd als tick-for-tick identiek onder de native renderer en bootte op de Old 3DS (hoewel deze te traag bleek voor release op dat platform). Het DASH-scherm voor het onderste scherm werd toegevoegd. Een laatste adversarial review controleerde het resultaat voor de v1.0.0 release.
Bronnen
Alle cijfers in dit document zijn gebaseerd op:
- Git-geschiedenis.
- Onderzoeksdocumenten in
docs/research/.
- Hardware-logs.
- Sessie-transcripten.
- Schattingen (zoals dollar-bedragen) zijn gebaseerd op gepubliceerde API-lijstprijzen toegepast op exacte token-aantallen.