dbreunig/nesformer

Games

Compiles an NES 6502 CPU and selected NROM games into fixed model weights, running them slowly as an exact emulation experiment.

154
6
Python
NOASSERTION
new today

nesformer is a proof-of-concept that places the NES's 6502 CPU, its 2 KB of work RAM and a cartridge's program ROM inside a standard Qwen3_5ForCausalLM checkpoint. Nobody trained the weights; a compiler computed them. When a game runs, the model predicts the CPU's execution log one token at a time, while a small host program draws pixels, reads the controller and triggers the vblank interrupt. It builds on the Qwenputer compiler and its trick of using the model's Gated DeltaNet state as machine memory.

What you can actually do

The CLI has run (play a ROM and save a GIF), check (compare the weights against a reference 6502 side by side, stopping at the first difference), trace (print the token stream), build (recompile the checkpoint) and info. Controller input is a frame-range script such as holding right+b or pressing a twice, so a game can be driven deterministically and the output captured as GIF or PNG.

What is and isn't inside the model

The weights contain the full official opcode set, addressing modes, flags, stack, BRK/NMI entry and 2 KB of RAM, plus 32 KB of PRG-ROM stored twice. The PPU, controllers, APU registers and NMI timing live in the host program, and the host never sees CPU registers or RAM except through the trace. The PPU renders one scanline at a time, so mid-scanline effects aren't reproduced, there is no sound, and sprite-0 hit plus sprite overflow are approximate. This matters if you expect a general NES emulator rather than a visual demo.

Requirements and limits

You need Python 3.11 or newer, numpy, scipy, numba and pillow, run from the top folder with the separately downloaded weights/ beside the package; the README includes a checksum command to verify the unzip. Only NROM cartridges (iNES mapper 0) work, and you must supply your own ROMs — the repository ships three freely licensed test ROMs. Games on bank-switching boards stop with a message. Unofficial opcodes and jumps into RAM emit HALT, IRQs (APU frame, DMC) are unsupported, BRK and NMI do work, and reads of $4020–$7FFF return 0.

Speed is the headline constraint: the default numba engine ran at about 1,650 tokens/s on one CPU core of the author's machine, numpy about 210 and stock transformers about 10, against roughly 700,000 tokens/s a real console would need. With idle-loop skipping, the README reports runs 150–290× slower than hardware; 600 frames (10 seconds of NES time) took around 25 minutes in the quick-start example.

How the claim was checked

The reference CPU matches nestest's golden log for 3,348 instructions and py65 on 5.7 million instructions; free-running weight runs are reported identical to the reference for nestest, Thwaite and Full Game, with all saved frames matching the project README's verification section. These are the author's own comparisons against conventional emulators, not an independent audit.

Licensing: nesformer is MIT, the adapted Qwenputer compiler code is MIT, and bundled test ROMs keep their own licences (Full Game MIT, Thwaite GPL-3.0). The author notes in the Show HN thread that the initial working code and weights came from two prompts to an AI model, using the emulation community's conformance tests as oracles discussion; that is background on how it was made, not a validation of it. The checkpoint is an ordinary Hugging Face folder loadable by stock transformers.

Written by AI from the project's README, updated October 30, 2026. The project's own docs are the source of truth.

Hacker News

Show HN: A working Nintendo in ~1GB of Qwen weights
▲ 169 · 105 comments · October 30, 2026