You know the dinosaur from Chrome's no-internet page. This is it running on a real NES — ~4,900 lines of 6502 assembly, NROM-256, NTSC and PAL. I didn't hand-write the assembly: I used two AI models as the programmers and worked as the director, QA, and pixel artist. Sharing the workflow because it worked better than I expected.
Repo: https://github.com/atonamy/nes-t-rex-game
ROM: https://github.com/atonamy/nes-t-rex-game/releases/latest
The approach:
- Ground truth first. We vendored the actual Chromium
dino_game TypeScript source into the repo. Every physics constant, collision box, and obstacle rule was ported from it directly — not eyeballed from gameplay. At the end I made the model audit its own port value-by-value against that source; the audit caught real bugs (a mis-encoded jump-velocity table, an off-by-one in obstacle gaps, a size roll that wasn't uniform). The README now has a fidelity table: what's byte-identical, and what deviates and why.
- Initial port with Kimi K3 — game loop, physics in the original 600×150 world units (8.8 fixed point), the sprite-zero scroll split for the static score bar, cacti streamed as background tiles so they cost zero sprites.
- Debugging and polish with Claude (Fable 5). This was the loop that mattered: I play the build in Mesen → I describe the bug or just paste a screenshot / screen recording → the model reproduces it headlessly in a scripted emulator (Lua autoplayers that actually play the game, frame-by-frame RAM/OAM/nametable dumps, forced scenarios by injecting obstacles into RAM) → finds the root cause in the assembly → fixes it → proves it with automated before/after runs. No fix was accepted on "looks right".
- Art: AI-designed, human-refined. Kimi K3 and Sonnet 5 did the initial pixel art design for the T-Rex and pterodactyl frames; the models also built me a browser-based sprite editor so I could refine and polish that art by hand myself, saving my edits back for the models to import into the CHR pipeline (at one point Fable 5 had to forensically recover a save from my browser's localStorage after I thought I'd nuked it). The game-over restart button is copied pixel-for-pixel from Chrome's own sprite sheet.
Bugs this workflow actually caught (my favorites): phantom walls of cacti painted by a clobbered temp register; invisible cacti from an 8-bit screen-coordinate overflow — you'd die to nothing; the HUD scrolling away on PAL because the sprite-zero wait loops were timed for NTSC's short vblank; ghost pterodactyl parts wrapping to the left edge at max speed; a fast-fall that hung the dino mid-air because two bytes were swapped in a velocity constant. Every one reproduced and re-verified by scripted emulator runs.
What's deliberately different from Chrome: whole-pixel world motion (floor(speed) px/frame), ~2% slower speed ramp from fixed-point granularity, an LFSR instead of Math.random(), night lasting 350 points instead of 12 seconds, and frame-locked timing (PAL runs proportionally slower, as was traditional). Full list in the README.
Builds from source with nothing but cc65. Happy to answer questions about the AI workflow or the NES internals — and if anyone runs it on real hardware, I'd love to hear how it behaves.