
2026/10/31 1:40
Show HN: Qwen 重みの約 1GB で稼働するニンテンドー
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
「nesformer」プロジェクトは、追加の学習なしで Qwen3.5 ラージ・ランゲージ・モデル(LLM)の内部に 8 ビットの任天堂エンターテインメントシステム(NES)CPU—具体的には 2A03 チップ—を実行する画期的な能力を demonstrates します。AI をプログラム可能ハードウェアとして扱い、特別製のコンパイラはマシンのワーク RAM、プログラム ROM、回路ロジックを直接モデルの Gated DeltaNet のウェイトと状態にマップします。小さなホストプログラムが外部機能(描画、コントローラー入力など)を管理し、モデルはトークン単位で CPU 命令を実行します。これ以前の「Qwenputer」研究(CHIP-8 および RISC-V コンパイル)を土台とし、このシステムは数百万回の命令のみを用いてモデル固有の bf16 フォーマットだけで標準エミュレータと同等の精度で Super Mario Bros. World 1-1 をプレイすることに成功しました。実装では Qwen3.5-4B の特定アーキテクチャ(16 キー頭、32 ヴァリュー頭、7 Gated DeltaNet レイヤ)を用い、bf16 で約 466.6M パラメータです。ユーザーは CLI コマンド(例:
python -m nesformer run roms/thwaite.nes)を通じてゲームを実行し、視覚的な GIF 出力を生成したり、参照 CPU に対して実行を検証(check)したり、トークンストリームをトレース(trace)したりできます。パフォーマンスはエンジン構成により大きく変動します:Numba は単一 CPU コアで約 1,650 トークン/秒、numpy は約 210 トークン/秒、標準トランスフォーマーは約 10 トークン/秒です。現在の制限により、バンクスイッチングまたは複雑なサウンドチップを持たない特定の NROM カートリッジ(マップャー 0)へのサポートのみが可能で、将来的なバージョンでは ROM 処理の拡張とフルな音声・映像コンポーネントの統合を目指しています。クレジットは MIT/GPL ライセンスの下で Qwenputer、nestest、および各種コミュニティ貢献者に帰属しています。本文
Qwen3.5 モデルに NES CPU が埋め込まれるプロジェクト「NESformer」について
標準的な Qwen3.5 モデルの重みに、NES の 6502 CPU(2A03 チップのコア)、2 KB のワーキング RAM、そしてゲームプログラム ROM がすべて埋め込まれています。
- ゲームの実行ログをトークンごとに逐次予測します。
- 画像描画やコントローラー入力などのコンソール動作は、それを囲む小さなホストプログラムが処理します。
このプロジェクトは、Divyansh Agrawal 氏の「Qwenputer」プロジェクト(CHIP-8 および RISC-V CPU を Qwen3.5 に編成した試み)の上に構築されています。Gated DeltaNet ステートを機械のメモリとして機能させる手法とコンパイラを再利用しています。
スーパーマリオブラザーズの実証
Doug Fraker 氏による『Super Mario Bros.'](ワールド 1-1)のフルゲームプレイが実現されています。
- タイトル画面から第一ステージまでを完全に動作させました。
- 配布されているテストゲームでは、各フレームの出力が従来の 6502 エミュレータの結果と完全に一致しています(検証方法 を参照)。
クイックスタート
1. フォルダ構成
nesformer.zip と nesformer-weights.zip を解凍し、以下の構造に配置してください。
重要: 重みはパッケージ内部ではなく、隣接するフォルダに置く必要があります。
nesformer/ <- ここからコマンドを実行 ├── nesformer/ <- Python パッケージ本体 ├── chipformer/ <- Qwenputer のコンパイラ ├── roms/ <- テスト用 ROM(自作 ROM もここ) ├── examples/ <- サンプル GIF とフレームシート ├── tests/ ├── LICENSE ├── pyproject.toml └── weights/ <- nesformer-weights.zip の展開先 ├── config.json ├── model.safetensors └── ...
SHA256 チェック: 展開が正常か確認するには以下のコマンドを実行してください。
shasum -a 256 -c weights/SHA256SUMS
注意:
フォルダがない場合や配置場所が違う場合は、weightsオプションを指定するか、パスを直接指定する必要があります。--weights
2. インストール
Python 3.11 以上の環境が必要です。
python3 -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install numpy scipy numba pillow
3. ゲームをプレイする
以下のコマンドでゲームを実行・描画します。
python -m nesformer run roms/thwaite.nes --frames 600 --show \ --buttons "start@90-95+200-205,a@230-233..."
動作特性
- 初回実行: エンジンと Numba のコンパイルに約 20 秒 かかります。
- 1 フレームあたり: 処理に 1〜6 秒 かかるため、全体的に動作は遅いです。
- 出力はターミナル上に描画され、終了時に同名の
ファイルが保存されます(例:.gif
)。thwaite.gif
自前の ROM をプレイする
任意の NROM ボード(iNES マップパ 0)を使用している
.nes ファイルを指定できます。
python -m nesformer run roms/smb.nes --frames 600 --show \ --buttons "start@60-65,right@200-600,a@250-265+300-315..."
- 設定済みのスクリプト(例:右へ移動しつつジャンプ)を指定すれば、ROM の状態を読み込むだけで実行できます。
- 制限: 他のマップパを使用するゲームは停止します(詳細は「制限事項」参照)。
コントローラースクリプトの記述法
--buttons オプションにはカンマ区切りのリストを指定します。
- 形式:
ボタン名@開始フレーム - 終了フレーム (+範囲) - 例:
: 60〜65 フレーム目にスタートボタンを押す。start@60-65
: 200〜600 フレーム間、右移動を保持する。right@200-600
: A ボタンを 2 回押し(250〜265 フレーム目、300〜315 フレーム目に)。a@250-265+300-315
利用可能なボタン
,a
,b
,select
,start
,up
,down
,leftright- フレームカウント: 電源投入時が
。60fps 環境のため、600 フレームは開始から 10 秒目 に相当します。0
コマンド一覧
| コマンド | 機能 |
|---|---|
| ROM を読み込み GIF を生成してプレイする |
| 重みと参照 CPU を並行実行し、不一致で停止する |
| モデルのトークンストリームを出力(デフォルト 40 トークン) |
| 回路をコンパイルし重みを生成 ( に書き込み、約 10 秒) |
| チェックポイントの情報を表示する |
run コマンドの詳細オプション
| オプション | デフォルト | 意味 |
|---|---|---|
| | N フレーム後に停止する |
| | コントローラー入力スクリプト |
| | ターミナルでフレームを描画(24 ビットカラー対応が必要) |
| | アニメーション GIF の保存先 |
| | フレームを PNG で保存(GIF 生成と併用可能) |
| | N 番目のフレームだけを保持する |
| | 保存画像を N 倍拡大 |
| | エンジン種類 (, , ) |
| | アイドル待機のループも実行する |
| | トークン ID をファイルに保存 |
共通オプション:
、run、checkはすべてtrace,--weights,--engine,--buttonsを受け付けます。--no-skip
仕組みの解説
モデル構成要素の分割
- モデル内(重み + DeltaNet ステート):
- 6502 コア: すべての命令コード、アドレッシングモード、フラグ、スタック等。
- RAM: 2 KB のワーキング RAM。
- ROM: 32 KB の PRG-ROM(命令フェッチ用・データ読み取り用の 2 副本保持)。
- ホストプログラム (
):nesformer/host.py- PPU レンダラー、コントローラー、APU レジスタ、NMI タイミングなど。
メモリトリック
各 DeltaNet ヘッドは
$128 \times 128$ のステート行列 を保持し、ゲート開放と 1-hot キーによって更新・読み書きを行います。これにより、カセットや RAM、レジスタの内容を行列の行として管理しています。
チェックポイント形式
- Hugging Face フォーマット(
)を使用。.safetensors
で直接読み込めます。Qwen3_5ForCausalLM.from_pretrained
層構造とレイヤー計画
モデルは Qwen3.5-4B の形状を継承しつつ、7 つの Gated DeltaNet レイヤーで回路部分を構成します。
| 層 | 注意力(ステート)主要内容 |
|---|---|
| 1 | PC、レジスタ (A, X, Y)、フラグ、ポインタラッチなど |
| 2 | PC の更新(アンカー + 実行バイト数) |
| 3 | PRG フェッチ(命令コードとオペランド)のデコード |
| 4 | 有効アドレス計算、プッシュ処理 |
| 5 | RAM/PRG データ読み取り、演算 (ADC/SBC/BIT) |
| 6 | 結果バイト、フラグ更新、ジャンプターゲット設定 |
| 7 | 次のトークン生成 |
トークンとトレース
- 大多数の命令は 1 トークン で処理されます(平均 1.1〜1.3 トークン/命令)。
- PC は明示的に書かれない代わりに、ジャンプターゲットやオフセットで計算されます。
- 例:
→ ポインターバイトをラッチし、ストアする動作をトークン化。STA ($72),Y
検証方法と性能評価
精度の検証結果
参照 CPU (
nesformer/cpu.py) とモデルの結果は完全に一致します。
| 実行種別 | トークン数 | フレーム/時間 | 結果 |
|---|---|---|---|
| nestest (公式命令) | 4,586 | HALT | 一致。期待通り終了。 |
| Thwaite (check) | 700,000 | 271 フレーム / 4.5s | トレーンスと一致。 |
| Thwaite (run) | 1,916,527 | 600 フレーム / 10.0s | 全フレーム一致。 |
| Full Game (run) | 2,645,885 | 420 フレーム / 7.0s | 保存された全フレーム一致。 |
- 速度性能:
- Numba (fast): 約 1,650 トークン/秒(CPU コアあたり)。
- NumPy: 約 210 トークン/秒。
- Standard Transformers (
): 約 10 トークン/秒。hf - 実際の NES との比較: 実機よりも 150〜290 倍遅いです(アイドルループを待っているため)。
制限事項
- NROM カセットのみ対応: iNES マップパ 0 のみ。大型ゲーム用バンクスイッチング(MMC1/3 など)は未実装。
- 公式命令コードのみ: 非公式な命令コードは
を発します。HALT - RAM へのジャンプ不可: RAM アドレスへの転送は禁止されています。
- IRQ 非対応: APU フレーム IRQ や DMC は動作せず、BRK および NMI のみ有効です。
- I/O レジスタの読み取り:
の読み取りは常に$4020–$7FFF
です(PRG-RAM なし)。0 - PPU と APU の制限:
- PPU は 1 スキャンラインずつ描画するため、途中の効果は再現されません。
- スプライト衝突やオーバーフローは近似のみ。
- 音声出力はありません。
テストと実行方法
テストスイートの実行
pip install pytest py65 python -m pytest -q tests
- 参照 CPU (
、py65) との比較を行います。nestest - アイドルループスキップ機能も検証されます。
標準 transformers エンジンでの実行
チェックポイントを
transformers ライブラリで直接使う場合:
pip install "torch>=2.6" "transformers>=5.22" python -m nesformer run roms/thwaite.nes --frames 3 --engine hf
- パディングトークンをデコードし、ステートをキャッシュに書き込む処理を含みます。
ファイル構成の概要
| パス | 内容 |
|---|---|
| トークンファミリと記録定義 |
| 参照用 6502 CPU (トレース出力) |
| PPU、コントローラー、NMI タイミング等のホストロジック |
| 回路と状態スナップショットの管理 |
| Qwen3_5ForCausalLM 形式へのエミッター |
| Qwenputer のコンパイラソース |
| コンパイル済みチェックポイント |
| テスト用 ROM ファイル群 |
| 実行結果の GIF ファイル |
クレジットとライセンス
- Qwenputer: MIT ライセンス(© 2026 Divyansh Agrawal)。
およびnesformer/core.py
は同ライセンスを適用。weights.py - テスト用 ROM:
- Kevin Horton (
)、Doug Fraker (nestest
, MIT)、Damian Yerrick (Full Game
, GPL-3.0)。Thwaite
- Kevin Horton (
- nesformer プロジェクト全体: MIT ライセンス。
フォルダ内の個別の ROM は各自のライセンスが適用されます(roms/
参照)。roms/SOURCES.md