<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>github.com/dbreunig</title>
  <subtitle>Browse aymeric&#39;s, an independent, searchable archive of readable snapshots from followed feeds, preserved in Git with aggr.</subtitle>
  <id>https://aggr.aymericbeaumet.com/sources/github.com/dbreunig/</id>
  <link rel="alternate" type="text/html" href="https://aggr.aymericbeaumet.com/sources/github.com/dbreunig/"/>
  <link rel="self" type="application/atom+xml" href="https://aggr.aymericbeaumet.com/sources/github.com/dbreunig/atom.xml"/>
  <updated>2026-10-30T16:40:22+00:00</updated>
  <author>
    <name>aymeric&#39;s</name>
  </author>
  <generator version="2.0.0" uri="https://github.com/aymericbeaumet/aggr">aggr</generator>
  <entry>
    <id>urn:aggr:item:2bcd69799a23d595351deb5e6a9908dfa4b5874a</id>
    <title type="text">Show HN: A working Nintendo in ~1GB of Qwen weights</title>
    <link rel="alternate" type="text/html" href="https://aggr.aymericbeaumet.com/items/hnrss-org/2026-10-30-show-hn-a-working-nintendo-in-1gb-of-qwen-weights/"/>
    <link rel="via" type="text/html" href="https://github.com/dbreunig/nesformer"/>
    <published>2026-10-30T16:40:22+00:00</published>
    <updated>2026-10-30T16:40:22+00:00</updated>
    <author>
      <name>dbreunig</name>
    </author>
    <category term="news"/>
    <source>
      <title>Hacker News: Front Page</title>
    </source>
    <summary type="text">An NES CPU compiled into the weights of a stock Qwen3.5 model. The NES&#39;s 6502 CPU (the core of its 2A03 chip), its 2 KB of work RAM, and a cartridge&#39;s program ROM run inside a standard Qwen3_5ForCausalLM checkpoint. Nobody trained these…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;An NES CPU compiled into the weights of a stock Qwen3.5 model.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The NES&#39;s 6502 CPU (the core of its 2A03 chip), its 2 KB of work RAM, and a cartridge&#39;s program ROM run inside a standard &lt;code&gt;Qwen3_5ForCausalLM&lt;/code&gt; checkpoint. Nobody trained these weights; a compiler computed every one. When you play a game, the model predicts the CPU&#39;s execution log one token at a time. A small host program plays the rest of the console around it: it draws the picture, reads the controller, and fires the vblank interrupt.&lt;/p&gt;
&lt;p&gt;nesformer builds on &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/divagr18/qwenputer&quot;&gt;Qwenputer&lt;/a&gt; by &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://divagr.com/blog/qwenputer&quot;&gt;Divyansh Agrawal&lt;/a&gt;, which compiled a CHIP-8 and then a RISC-V CPU into Qwen3.5-4B. It reuses Qwenputer&#39;s compiler and its central trick: &lt;strong&gt;the model&#39;s Gated DeltaNet state is the machine&#39;s memory.&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Super Mario Bros. (World 1-1)&lt;/th&gt;
&lt;th&gt;Full Game by Doug Fraker (title screen and first level)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/dbreunig/nesformer/blob/main/examples/demo.gif&quot;&gt;&lt;picture class=&quot;article-picture article-picture-fallback&quot; style=&quot;--image-ratio:16 / 9&quot;&gt;&lt;img src=&quot;https://github.com/dbreunig/nesformer/raw/main/examples/demo.gif&quot; alt=&quot;Super Mario Bros., played by the weights&quot; loading=&quot;eager&quot; decoding=&quot;async&quot; fetchpriority=&quot;high&quot; referrerpolicy=&quot;no-referrer&quot; class=&quot;progressive-image&quot;&gt;&lt;/picture&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/dbreunig/nesformer/blob/main/examples/full_game.gif&quot;&gt;&lt;picture class=&quot;article-picture article-picture-fallback&quot; style=&quot;--image-ratio:16 / 9&quot;&gt;&lt;img src=&quot;https://github.com/dbreunig/nesformer/raw/main/examples/full_game.gif&quot; alt=&quot;Full Game, played by the weights&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;low&quot; referrerpolicy=&quot;no-referrer&quot; class=&quot;progressive-image&quot;&gt;&lt;/picture&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Every CPU token in these runs came from the model. For the bundled test games, every frame also matches a conventional 6502 emulator&#39;s output exactly (see &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/dbreunig/nesformer#how-it-was-checked&quot;&gt;How it was checked&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Quick start&lt;/h2&gt;
&lt;h3&gt;1. Folder layout&lt;/h3&gt;
&lt;p&gt;Unzip &lt;code&gt;nesformer.zip&lt;/code&gt; and &lt;code&gt;nesformer-weights.zip&lt;/code&gt; into the same folder. The weights go &lt;em&gt;next to&lt;/em&gt; the &lt;code&gt;nesformer/&lt;/code&gt; package, not inside it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;code-snippet&quot;&gt;nesformer/              &amp;lt;- run commands from here
├── nesformer/          &amp;lt;- the Python package
├── chipformer/         &amp;lt;- Qwenputer&amp;#39;s compiler
├── roms/               &amp;lt;- test ROMs (put your own here too)
├── examples/           &amp;lt;- sample GIFs and frame sheets
├── tests/
├── LICENSE
├── LICENSE.chipformer
├── README.md
├── pyproject.toml
└── weights/            &amp;lt;- from nesformer-weights.zip
    ├── config.json
    ├── generation_config.json
    ├── model.safetensors
    ├── nesformer.json
    └── SHA256SUMS
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The CLI looks for &lt;code&gt;weights/&lt;/code&gt; beside the &lt;code&gt;nesformer/&lt;/code&gt; package. To keep the weights elsewhere, pass &lt;code&gt;--weights /path/to/weights&lt;/code&gt; to &lt;code&gt;run&lt;/code&gt;, &lt;code&gt;check&lt;/code&gt; or &lt;code&gt;trace&lt;/code&gt;, or give the path to &lt;code&gt;info&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To confirm the weights unzipped correctly, run &lt;code&gt;shasum -a 256 -c weights/SHA256SUMS&lt;/code&gt; from the top folder.&lt;/p&gt;
&lt;h3&gt;2. Install&lt;/h3&gt;
&lt;p&gt;You need Python 3.11 or newer.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;Shell&quot;&gt;&lt;span class=&quot;syntax-source syntax-shell syntax-bash&quot;&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-shell&quot;&gt;python3&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-arguments syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; -&lt;/span&gt;m&lt;/span&gt; venv .venv&lt;/span&gt;
&lt;span class=&quot;syntax-meta syntax-function-call syntax-shell&quot;&gt;&lt;span class=&quot;syntax-support syntax-function syntax-source syntax-shell&quot;&gt;source&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-arguments syntax-shell&quot;&gt; .venv/bin/activate          &lt;span class=&quot;syntax-comment syntax-line syntax-number-sign syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-begin syntax-shell&quot;&gt;#&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-comment syntax-line syntax-number-sign syntax-shell&quot;&gt; Windows: .venv\Scripts\activate&lt;/span&gt;&lt;span class=&quot;syntax-comment syntax-line syntax-number-sign syntax-shell&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-shell&quot;&gt;pip&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-arguments syntax-shell&quot;&gt; install numpy scipy numba pillow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Play a game&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;Shell&quot;&gt;&lt;span class=&quot;syntax-source syntax-shell syntax-bash&quot;&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-shell&quot;&gt;python&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-arguments syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; -&lt;/span&gt;m&lt;/span&gt; nesformer run roms/thwaite.nes&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; --&lt;/span&gt;frames&lt;/span&gt; 600&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; --&lt;/span&gt;show&lt;/span&gt; &lt;span class=&quot;syntax-punctuation syntax-separator syntax-continuation syntax-line syntax-shell&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt;  --&lt;/span&gt;buttons&lt;/span&gt; &lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-shell&quot;&gt;&amp;quot;&lt;/span&gt;start@90-95+200-205,a@230-233+250-253+270-273+290-293+310-313+330-333+350-353+370-373+390-393+410-413+430-433+450-453+470-473+490-493+510-513+530-533+550-553+570-573+590-593&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-shell&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;--show&lt;/code&gt; draws each frame in your terminal as the model generates it. When the run ends, the CLI saves an animated GIF named after the ROM (here &lt;code&gt;thwaite.gif&lt;/code&gt;) in the current folder.&lt;/p&gt;
&lt;p&gt;Expect it to be slow. The first run spends about 20 seconds compiling the engine with numba. After that, a frame takes 1–6 seconds, so 600 frames (10 seconds of NES time) take around 25 minutes.&lt;/p&gt;
&lt;h2&gt;Playing your own ROMs&lt;/h2&gt;
&lt;p&gt;Point &lt;code&gt;run&lt;/code&gt; at any &lt;code&gt;.nes&lt;/code&gt; file that uses the NROM board (iNES mapper 0), such as Super Mario Bros., Donkey Kong or Excitebike. You supply the ROM; nesformer only ships the three freely licensed test ROMs in &lt;code&gt;roms/&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;Shell&quot;&gt;&lt;span class=&quot;syntax-source syntax-shell syntax-bash&quot;&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-shell&quot;&gt;python&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-arguments syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; -&lt;/span&gt;m&lt;/span&gt; nesformer run roms/smb.nes&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; --&lt;/span&gt;frames&lt;/span&gt; 600&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; --&lt;/span&gt;show&lt;/span&gt; &lt;span class=&quot;syntax-punctuation syntax-separator syntax-continuation syntax-line syntax-shell&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt;  --&lt;/span&gt;buttons&lt;/span&gt; &lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-shell&quot;&gt;&amp;quot;&lt;/span&gt;start@60-65,right@200-600,a@250-265+300-315+360-375+420-435+480-495+540-555&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-shell&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That script starts the game, then walks Mario right and jumps about once a second. The CLI loads the ROM into the model&#39;s state at startup, so the same weights run any NROM game without a rebuild. Games on other boards stop with a message: see &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/dbreunig/nesformer#limitations&quot;&gt;Limitations&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Controller scripts&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;--buttons&lt;/code&gt; takes a comma-separated list of entries. Each entry names one or more buttons joined by &lt;code&gt;+&lt;/code&gt;, then &lt;code&gt;@&lt;/code&gt;, then one or more frame ranges joined by &lt;code&gt;+&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;code-snippet&quot;&gt;start@60-65                 press Start during frames 60 to 65
right@200-600               hold Right from frame 200 to frame 600
a@250-265+300-315           press A twice
right+b@200-600             hold Right and B together (run, in Super Mario Bros.)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The buttons are &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;select&lt;/code&gt;, &lt;code&gt;start&lt;/code&gt;, &lt;code&gt;up&lt;/code&gt;, &lt;code&gt;down&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;. Frames count from power-on at 60 per second, so frame 600 is 10 seconds in. Games ignore input on screens where you can&#39;t move, so holding a button a little early does no harm. In Super Mario Bros., a longer A press makes a higher jump.&lt;/p&gt;
&lt;h2&gt;Commands&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python -m nesformer run ROM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Play a ROM on the weights and save a GIF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python -m nesformer check ROM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run the weights and the reference CPU side by side; stop at the first difference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python -m nesformer trace ROM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Print the model&#39;s token stream (default 40 tokens)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python -m nesformer build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compile the circuit and write &lt;code&gt;weights/&lt;/code&gt; (about 10 seconds)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python -m nesformer info&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Describe the checkpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Options for &lt;code&gt;run&lt;/code&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--frames N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;Stop after N frames&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--buttons SCRIPT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Controller input (see above)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--show&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;off&lt;/td&gt;
&lt;td&gt;Draw frames in the terminal (needs 24-bit color, e.g. iTerm2 or Windows Terminal)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--gif PATH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ROM name&lt;/td&gt;
&lt;td&gt;Where to save the animated GIF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--png DIR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;off&lt;/td&gt;
&lt;td&gt;Save each kept frame as a PNG in DIR. With &lt;code&gt;--png&lt;/code&gt; alone, no GIF is saved. Add &lt;code&gt;--gif&lt;/code&gt; to get both.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--every N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Keep every N-th frame&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--scale N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Enlarge saved frames N times&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--engine&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fast&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fast&lt;/code&gt; (numba), &lt;code&gt;numpy&lt;/code&gt;, or &lt;code&gt;hf&lt;/code&gt; (stock transformers; needs torch, ~10 tokens/s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--no-skip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;off&lt;/td&gt;
&lt;td&gt;Run every iteration of idle wait loops (slower; identical frames)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--max-tokens N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Stop after N tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--trace FILE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Save the token ids&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;run&lt;/code&gt;, &lt;code&gt;check&lt;/code&gt; and &lt;code&gt;trace&lt;/code&gt; all accept &lt;code&gt;--weights&lt;/code&gt;, &lt;code&gt;--engine&lt;/code&gt;, &lt;code&gt;--buttons&lt;/code&gt; and &lt;code&gt;--no-skip&lt;/code&gt;. &lt;code&gt;check --tokens N&lt;/code&gt; sets how far to compare (default 50,000). &lt;code&gt;trace --tokens N&lt;/code&gt; sets how many tokens to print (default 40). &lt;code&gt;build --out DIR&lt;/code&gt; writes the checkpoint somewhere other than &lt;code&gt;weights/&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;How it works&lt;/h2&gt;
&lt;h3&gt;What&#39;s in the weights, and what isn&#39;t&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;In the model (weights + DeltaNet state)&lt;/th&gt;
&lt;th&gt;In the host (&lt;code&gt;nesformer/host.py&lt;/code&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The 6502 core: all 151 official opcodes, every addressing mode, flags, stack, BRK and NMI entry&lt;/td&gt;
&lt;td&gt;The PPU: a scanline renderer and the palette&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 KB of work RAM&lt;/td&gt;
&lt;td&gt;Controllers; APU registers (written, otherwise ignored)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32 KB of PRG-ROM, stored twice: one copy for instruction fetch, one for data reads&lt;/td&gt;
&lt;td&gt;NMI timing at vblank, injected as an &lt;code&gt;NMI&lt;/code&gt; token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OAM DMA reads (the 256 bytes appear as &lt;code&gt;DM&lt;/code&gt; tokens)&lt;/td&gt;
&lt;td&gt;Answers to I/O reads, injected as &lt;code&gt;IN&lt;/code&gt; tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This split follows Qwenputer&#39;s CHIP-8 build, whose host injects timer ticks and draws the display from the trace. The host never sees the CPU&#39;s registers or RAM except through the trace.&lt;/p&gt;
&lt;p&gt;The memory trick works like this. Each DeltaNet head keeps a 128 × 128 state matrix that the delta rule updates at every token. With the gate held open and a one-hot key, an update overwrites exactly one row of that matrix, and a one-hot query reads it back. So every row is a memory cell, and the cartridge, RAM and registers all live in rows.&lt;/p&gt;
&lt;h3&gt;The checkpoint&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;weights/&lt;/code&gt; is an ordinary Hugging Face folder. It loads with &lt;code&gt;Qwen3_5ForCausalLM.from_pretrained&lt;/code&gt; and needs no custom code.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Architecture&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Qwen3_5ForCausalLM&lt;/code&gt;, with Qwen3.5-4B&#39;s DeltaNet head shapes (16 key heads, 32 value heads, dim 128) and MLP width (9,216)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layers&lt;/td&gt;
&lt;td&gt;7 Gated DeltaNet layers (the circuit), plus 1 all-zero attention layer that Hugging Face&#39;s cache needs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hidden size&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vocabulary&lt;/td&gt;
&lt;td&gt;263,808 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parameters&lt;/td&gt;
&lt;td&gt;466.6M in bf16 (933 MB), of which &lt;strong&gt;9.3M are nonzero&lt;/strong&gt;, so the weights zip to 3.3 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;nesformer.json&lt;/code&gt; records which layer and head holds each part of the machine. A run writes the cartridge, registers and RAM into those DeltaNet states, then decodes greedily.&lt;/p&gt;
&lt;h3&gt;Layer plan&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Attention (state)&lt;/th&gt;
&lt;th&gt;MLP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;PC anchor; instruction counters; A, X, Y, SP; flags N V Z C I D; pointer latches; NMI flag&lt;/td&gt;
&lt;td&gt;counter thermometers; SP ± 1; LO + Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;PC = anchor + bytes executed since; PC + 1, PC + 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;PRG fetch: opcode and two operand bytes at the PC&lt;/td&gt;
&lt;td&gt;opcode decode; operand bits; indexed sums; branch test and target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;effective address, by addressing mode and record stage; the byte a push stores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;RAM and PRG data reads at the effective address&lt;/td&gt;
&lt;td&gt;operand; ADC/SBC adder, compares, BIT; address decode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;result byte, carry, overflow, flags, jump targets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;the next token&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;The trace&lt;/h3&gt;
&lt;p&gt;Each instruction becomes a record, and the record&#39;s last token commits it. As in Qwenputer&#39;s RISC-V core, the PC is implied rather than written: each final token carries its instruction&#39;s length, three DeltaNet counters tally the instructions of each length since the last jump, and the PC is the jump target plus that offset. Excerpts from Full Game:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;code-snippet&quot;&gt;SEI            P(000100 px0 L1)
LDX #$40       X($40 c0 v0 px0 L2)
STX $4017      IOW($4017=$40 L3)
TXS            S($FF L1)
BIT $2002      IOR($2002) IN($00) P(000110 px0 L3)       &amp;lt;- the host injects IN
BPL $8017      J($8017)
JSR $8279      PSH($FE) PSH($FD) J($8279)                 &amp;lt;- the return address is pushed in-circuit
RTS            PUL($FC) LO($7B) PUL($FD) J($827C)
STA ($72),Y    LO($08) HI($03) ST($00 a7=0 L2)            &amp;lt;- pointer bytes latched, then the store
STA $4014      IOW($4014=$02 L0) DM(0:$FF) … DM(255:$00) NT(L3)   &amp;lt;- OAM DMA
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Most instructions take a single token; real game code averages 1.1–1.3 tokens per instruction. &lt;code&gt;nesformer/spec.py&lt;/code&gt; documents every token family.&lt;/p&gt;
&lt;h2&gt;How it was checked&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The reference CPU&lt;/strong&gt; (&lt;code&gt;nesformer/cpu.py&lt;/code&gt;) matches nestest&#39;s golden log for 3,348 instructions, and the py65 emulator on 5.7 million instructions of game code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The exact circuit&lt;/strong&gt;, run in Qwenputer&#39;s evaluator with its bf16 exactness checks, predicts every reference token: all of nestest plus 283,610 positions of two games&#39; boot sequences.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The checkpoint in stock transformers&lt;/strong&gt; (bf16, CPU) predicts 2,651 positions of nestest and Full Game with no mismatches.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The weights, free-running&lt;/strong&gt;, generate traces identical to the reference CPU&#39;s:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;Tokens&lt;/th&gt;
&lt;th&gt;Frames&lt;/th&gt;
&lt;th&gt;NES time&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;nestest (official opcodes)&lt;/td&gt;
&lt;td&gt;4,586&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;identical, ending in the expected HALT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thwaite, &lt;code&gt;check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;700,000&lt;/td&gt;
&lt;td&gt;271&lt;/td&gt;
&lt;td&gt;4.5 s&lt;/td&gt;
&lt;td&gt;identical trace and frames&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thwaite, &lt;code&gt;run&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,916,527&lt;/td&gt;
&lt;td&gt;600&lt;/td&gt;
&lt;td&gt;10.0 s&lt;/td&gt;
&lt;td&gt;all 300 saved frames match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full Game, &lt;code&gt;run&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2,645,885&lt;/td&gt;
&lt;td&gt;420&lt;/td&gt;
&lt;td&gt;7.0 s&lt;/td&gt;
&lt;td&gt;all 210 saved frames match&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The idle-loop skip&lt;/strong&gt; changes nothing visible: frames and I/O writes, cycle timestamps included, match a run without it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Speed&lt;/h2&gt;
&lt;p&gt;The default engine computes Qwen3.5&#39;s forward pass from &lt;code&gt;model.safetensors&lt;/code&gt;, compiled with numba and skipping the all-zero blocks. It ran at about 1,650 tokens/s on one CPU core of the machine it was built on. The plain numpy engine does about 210, and stock transformers about 10. A real NES would need about 700,000 tokens per second.&lt;/p&gt;
&lt;p&gt;Games spend most of each frame in a loop that waits for vblank. When the host sees a loop body repeat exactly, with no RAM or I/O writes, it advances the clock to just before the next PPU event, and the remaining iterations still run. That cuts the token count by 2.6× to 4.2×. Overall, nesformer runs 150–290× slower than the real console.&lt;/p&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NROM cartridges only (iNES mapper 0).&lt;/strong&gt; The CPU can address only 32 KB of program ROM at a time. Bigger games carry a bank-switching chip (a &lt;em&gt;mapper&lt;/em&gt;, such as MMC1 or MMC3) that swaps which part of the ROM the CPU sees. nesformer&#39;s ROM reads happen inside the model, from a fixed 32 KB table, so it can&#39;t follow a bank switch yet. Supporting a mapper means storing the whole ROM in the state, keeping the bank registers there too, and adding one stage that turns each CPU address into a ROM address.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Official opcodes only.&lt;/strong&gt; An unofficial opcode emits &lt;code&gt;HALT&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code must run from the cartridge ROM.&lt;/strong&gt; A jump into RAM emits &lt;code&gt;HALT&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No IRQs&lt;/strong&gt; (APU frame IRQ, DMC). BRK and NMI work.&lt;/li&gt;
&lt;li&gt;Read-modify-write instructions on I/O registers don&#39;t produce an I/O write, and $4020–$7FFF reads as 0 (no PRG-RAM).&lt;/li&gt;
&lt;li&gt;The PPU and APU aren&#39;t in the weights. The PPU renders one scanline at a time, so mid-scanline effects aren&#39;t reproduced. Sprite-0 hit and sprite overflow are approximate, and there&#39;s no sound.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tests&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;Shell&quot;&gt;&lt;span class=&quot;syntax-source syntax-shell syntax-bash&quot;&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-shell&quot;&gt;pip&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-arguments syntax-shell&quot;&gt; install pytest py65&lt;/span&gt;
&lt;span class=&quot;syntax-meta syntax-function-call syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-shell&quot;&gt;python&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-arguments syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; -&lt;/span&gt;m&lt;/span&gt; pytest&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; -&lt;/span&gt;q&lt;/span&gt; tests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The tests take a few minutes. They check the reference CPU against nestest&#39;s log, the circuit against the reference, the weights free-running against the reference, and the idle-loop skip.&lt;/p&gt;
&lt;h2&gt;Running the checkpoint in stock transformers&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;Shell&quot;&gt;&lt;span class=&quot;syntax-source syntax-shell syntax-bash&quot;&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-shell&quot;&gt;pip&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-arguments syntax-shell&quot;&gt; install &lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-shell&quot;&gt;&amp;quot;&lt;/span&gt;torch&amp;gt;=2.6&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-shell&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-shell&quot;&gt;&amp;quot;&lt;/span&gt;transformers&amp;gt;=5.22&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-shell&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;syntax-meta syntax-function-call syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-shell&quot;&gt;python&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-arguments syntax-shell&quot;&gt;&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; -&lt;/span&gt;m&lt;/span&gt; nesformer run roms/thwaite.nes&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; --&lt;/span&gt;frames&lt;/span&gt; 3&lt;span class=&quot;syntax-variable syntax-parameter syntax-option syntax-shell&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-parameter syntax-shell&quot;&gt; --&lt;/span&gt;engine&lt;/span&gt; hf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;nesformer/hfcheck.py&lt;/code&gt; shows the whole procedure: load the checkpoint, decode one padding token, write the machine&#39;s state into the cache&#39;s DeltaNet states, then feed tokens one at a time.&lt;/p&gt;
&lt;h2&gt;Files&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Contents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nesformer/spec.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;token families and records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nesformer/cpu.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the reference 6502 that writes the trace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nesformer/host.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;everything around the CPU: PPU, controllers, NMI timing, cycle counting, idle skip&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nesformer/core.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the circuit and the state snapshot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nesformer/weights.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the emitter that turns the circuit into a &lt;code&gt;Qwen3_5ForCausalLM&lt;/code&gt; checkpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nesformer/engine.py&lt;/code&gt;, &lt;code&gt;fastengine.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;run the weights (numpy / numba)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nesformer/hfcheck.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;run the weights in stock transformers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nesformer/run.py&lt;/code&gt;, &lt;code&gt;check.py&lt;/code&gt;, &lt;code&gt;cli.py&lt;/code&gt;, &lt;code&gt;__main__.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;drivers, the teacher-forced check, the CLI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chipformer/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Qwenputer&#39;s q35 compiler (&lt;code&gt;q35/&lt;/code&gt; emitter and primitives, &lt;code&gt;dsl/&lt;/code&gt; graph)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;weights/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the compiled checkpoint and its SHA-256 checksum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;roms/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;test ROMs; &lt;code&gt;roms/SOURCES.md&lt;/code&gt; lists their authors and licenses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;examples/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GIFs and frame sheets from the runs; &lt;code&gt;demo.gif&lt;/code&gt; is the Super Mario Bros. run shown at the top&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tests/test_nesformer.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the test suite&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Credits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/divagr18/qwenputer&quot;&gt;Qwenputer&lt;/a&gt; and its &lt;code&gt;chipformer&lt;/code&gt; compiler: MIT, © 2026 Divyansh Agrawal (&lt;code&gt;LICENSE.chipformer&lt;/code&gt;). That license also covers the code adapted from Qwenputer in &lt;code&gt;nesformer/core.py&lt;/code&gt; and &lt;code&gt;nesformer/weights.py&lt;/code&gt;. Its last paragraph refers to Qwenputer&#39;s CHIP-8 ROMs, which this repository does not include.&lt;/li&gt;
&lt;li&gt;Test ROMs: nestest by Kevin Horton; Full Game by Doug Fraker (MIT); Thwaite by Damian Yerrick (GPL-3.0, source at &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/pinobatch/thwaite-nes&quot;&gt;pinobatch/thwaite-nes&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;License&lt;/h2&gt;
&lt;p&gt;nesformer is released under the MIT License (see &lt;code&gt;LICENSE&lt;/code&gt;). The ROMs in &lt;code&gt;roms/&lt;/code&gt; keep their own licenses, listed in &lt;code&gt;roms/SOURCES.md&lt;/code&gt;.&lt;/p&gt;
</content>
  </entry>
</feed>
