nesformer: Running a Nintendo Entertainment System inside Qwen 3.5 weights

NES Emulation via LLM Weights

nesformer is a technical implementation that compiles a complete Nintendo Entertainment System (NES) 6502 CPU, 2 KB of work RAM, and cartridge ROM into the weights of a stock Qwen3_5ForCausalLM model. Rather than training the model, the project uses a compiler to compute specific weight values that represent the machine's state. When a game runs, the model predicts the CPU's execution trace token-by-token, while a host program manages peripherals like the display, controllers, and vblank interrupts.

This project builds on the Qwenputer architecture, which previously demonstrated this technique with CHIP-8 and RISC-V cores. The central innovation is using the model's Gated DeltaNet state as the machine's memory, where specific rows in the state matrix function as memory cells for registers, RAM, and ROM.

Technical Architecture

The nesformer checkpoint is a standard Hugging Face folder that requires no custom model code to load. The system relies on the following structural split:

  • Inside the Model (Weights + DeltaNet State): The 6502 core, including all 151 official opcodes, addressing modes, flags, stack, and 2 KB of work RAM. The cartridge PRG-ROM is stored twice—once for instruction fetching and once for data reads.
  • Inside the Host (host.py): The PPU (scanline renderer), controller input handling, APU register writes, and NMI timing. The host acts as an I/O bridge, injecting NMI and data read tokens into the model's stream.

Each Gated DeltaNet head maintains a 128 × 128 state matrix. By holding the gate open and using one-hot keys, the system can overwrite or read back specific rows, effectively creating a persistent memory space within the transformer's recurrent state.

Performance and Limitations

While functional, nesformer is significantly slower than native hardware, running approximately 150–290× slower than a real NES. The system requires roughly 700,000 tokens per second for real-time performance, whereas the current implementation achieves roughly 1,650 tokens/s on a single CPU core using a Numba-compiled engine.

Key limitations include:

  • NROM Support Only: It is currently restricted to iNES mapper 0 (32 KB PRG-ROM). Bank-switching mappers are not yet supported.
  • Instruction Set: Only official 6502 opcodes are implemented; unofficial opcodes trigger a HALT.
  • Hardware Fidelity: The PPU and APU are not simulated within the weights, meaning there is no audio and mid-scanline PPU effects are not captured.

Community Insights and Discussion

The project has sparked debate regarding the efficiency of LLMs as a computing substrate. Commenters noted the stark contrast between the efficiency of deterministic assembly code and the compute-heavy nature of transformer-based emulation.

"I love these hacks, even though from an efficiency point of view it is horrifying to my assembly-code-golfing-brain. And it also gives some new appreciation for how much more efficient deterministic programs are compared to AI." — jacquesm

Others pointed out the broader implications for LLM capabilities, suggesting that this proves LLMs can function as universal computing mediums, potentially hosting VMs or tools internally rather than relying on external tool-calling loops.

"In principle one could compile a small VM inside the LLM weights... Instead of LLMs having to do slow autoregressive token emission with the current 'external' tool calling, it could literally execute everything except web search, inside the LLM, with just matmul operations." — armcat

Despite the performance overhead, the project serves as a rigorous stress test for the Gated DeltaNet architecture and highlights the potential for using LLMs as a deterministic, stateful execution environment.

Sources

Related