$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ファミコンに思いを馳せる〜エミュレータ自作を添えて〜
Search
noharu36
December 01, 2025
Programming
0
3
ファミコンに思いを馳せる〜エミュレータ自作を添えて〜
noharu36
December 01, 2025
Tweet
Share
More Decks by noharu36
See All by noharu36
検証!会津は本当に地盤が硬いのか?
noharu36
0
2
自作オブジェクトストレージをRustで
noharu36
0
1
shell自作した話
noharu36
0
4
Rustを布教したい
noharu36
0
7
neofetchよ、永遠に
noharu36
0
2
ISSの軌道計算をRustで
noharu36
0
6
Other Decks in Programming
See All in Programming
しっかり学ぶ java.lang.*
nagise
1
470
Microservices rules: What good looks like
cer
PRO
0
370
FluorTracer / RayTracingCamp11
kugimasa
0
170
手が足りない!兼業データエンジニアに必要だったアーキテクチャと立ち回り
zinkosuke
0
260
目的で駆動する、AI時代のアーキテクチャ設計 / purpose-driven-architecture
minodriven
11
3.8k
CSC305 Lecture 17
javiergs
PRO
0
240
Level up your Gemini CLI - D&D Style!
palladius
1
160
JEP 496 と JEP 497 から学ぶ耐量子計算機暗号入門 / Learning Post-Quantum Crypto Basics from JEP 496 & 497
mackey0225
2
550
データファイルをAWSのDWHサービスに格納する / 20251115jawsug-tochigi
kasacchiful
2
100
『実践MLOps』から学ぶ DevOps for ML
nsakki55
2
530
俺流レスポンシブコーディング 2025
tak_dcxi
13
6.9k
UIデザインに役立つ 2025年の最新CSS / The Latest CSS for UI Design 2025
clockmaker
16
6.1k
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
95
14k
YesSQL, Process and Tooling at Scale
rocio
174
15k
A Tale of Four Properties
chriscoyier
162
23k
Site-Speed That Sticks
csswizardry
13
980
The Art of Programming - Codeland 2020
erikaheidi
56
14k
Leading Effective Engineering Teams in the AI Era
addyosmani
8
1.2k
Designing Experiences People Love
moore
142
24k
Facilitating Awesome Meetings
lara
57
6.6k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Building Adaptive Systems
keathley
44
2.9k
Large-scale JavaScript Application Architecture
addyosmani
514
110k
4 Signs Your Business is Dying
shpigford
186
22k
Transcript
ファミコンに思いを馳せる 〜エミュレータ自作を添えて〜 学部2年 harukun
自己紹介 • 名前: 能島明希 • ハンドルネーム: harukun • 出身: 広島->岡山->大阪->東京->会津 • 技術: フロント(React+TS), バックエンド(Rust,
Go勉強中), その他(Rust, Haskell勉強中), Rust(Rust) • 好きなもの: ゲーム、タバコ、炒飯、 Rust、Neovim • 落とした単位数: おそらく同期内1位 • Twitter: https://twitter.com/pieceofharuki • Blog: https://zenn.dev/haru_blog
ファミコンとは
基本情報 • 1983年7月15日発売 正式名称ファミリーコンピュータ • 累計出荷台数6000万台 • 当時の家庭用ゲーム機 脅威の80%シェア • 世帯普及率25% 小中学生がいる家庭のほとんど •
スーパーマリオブラザーズ 世界売上 4000万本 2020年にあつ森に抜かれるまで 30年以上国内売上1位 今でも歴代世界売上本数6位
技術 • CPU Ricoh 2A03 MOS 6502(Apple Ⅱに搭載)をカスタマイズしたもの 当時よく使われていたz80に比べクロック数は劣るが、チップ面積が1/4でコストを削減できた 当時日本ではほぼ無名でリバースエンジニアリングされづらかった(ナムコは執念で解析した)
• ROM USBメモリとは違う メモリにアクセスするようにCPUから直接アクセスできて早い(カセットの中身をメモリに展開する必要がない) キャラクターROMとプログラムROMに分かれている • APU(オーディオプロセッシングユニット) CPUに内蔵されている 主にパルス波・三角波・ノイズで構成されている • PPU(ピクチャープロセッシングユニット) Ricoh 2C02(最初期) Apple Ⅱ
ファミコンエミュレータ自作してみた
Why • Rustでものづくりしたかった • 低レイヤなことにも少し興味があった • ちょうどGWだから何か作ろうと思った • 9月ごろに一回挑戦して失敗したから再挑戦することにした •
Rust書きたかった
技術スタック
実装の流れ 1. NES(ファミコンのこと)についておおまかに理解する 2. アセンブラの復習 3. CPUの実装 4. BUSの実装 5.
テスト、そして圧倒的デバッグ 6. PPUの実装 7. コントローラーの実装 8. (スクロールの実装) 9. APUの実装 //まだ!
ファミコンについて大まかに理解する • アーキテクチャ OSがないのでアプリケーション層が直接ハードウェアと通信する • CPUとPPUは直接カセットに接続できる • カセットを挿入するとCPUがプログラムROMに、PPUがキャラクターROMに接 続される •
CPUのメモリは2KiB(2048B)しかなかった • CPUの内部にAPUが実装されている • CPUにはWRAMという2KiBのメモリが接続されている • PPUにはVRAMという背景情報・スプライト情報などが格納される 2KiBのメモリ が接続されている • CPUは直接VRAMにアクセスできないが、PPUのレジスタを介してアクセスで きる
https://qiita.com/bokuweb/items/1575337bef44ae82f4d3#%E7%B0%A1%E6%98%93%E3%83%8F%E3%83%BC%E3%83%89%E3%82% A6%E3%82%A7%E3%82%A2%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E5%9B%B3
CPUの実装 • アドレスによってどこにアクセスできるか決まる • メモリアクセスは比較的遅いので非常に速くアクセスできるレジ スタと呼ばれる内部メモリ スロットがいくつかある ◦ レジスタのみにアクセス ◦
RAMの最初の255バイトへのアクセス • 上記に注意しながら約150の命令を実装する(白目)
こんな感じで命令を羅列して こんな感じで命令を実装して こんな感じで分岐を書く
これでようやくHello Worldができた
テスト テスト用のROMを読み込んで実行する diffコマンドを用いて実行ログとテスト用の ログを比較する (左が実行結果 右がテスト用ログ 左右が等しくなれば正常) すると実装されてない命令がいくつか (110個)あることがわかる これらは非公式命令と言われていて、 6502には公式に実装されていなかったが多くのゲームで使われている命 令たちなので、追加で全部実装する
()
こんな感じで命令を羅列して こんな感じで命令を実装して こんな感じで分岐を書く(ヤケクソ)
PPUの実装 • レジスタ CPUとの接続に使う( CPUアドレス空間の0x2000~0x2007) • 内部メモリとしてスプライトの状態を保持する OAMを持つ(256B) • 描画サイクル
◦ PPUは1秒間に262ラインレンダリングする ◦ NESの解像度は320 x 240 ◦ よって262-240=21ラインは画面に映らない ◦ 241ライン目に入ると VBlankというNMI割り込み命令が CPUに送 られる ◦ この間PPUのメモリは変更されないので CPUから自由にアクセス できるため次のフレームのために画面の状態を更新する
だるかったこと PPUは1クロックサイクルで1ドット描写する PPUはCPUの3倍高速なのでCPU1クロックサイクル=PPU3クロックサイクル PPUとCPUのクロックサイクルを合わせてあげないと画面が崩れてしまう 1ラインごとのPPUのクロックサイクルは341 1フレーム毎に341x262=89342PPUクロックサイクルになる CPUは29780CPUクロックサイクルごとにNMI割り込みを受ける
• まずCPUの命令毎にクロックサイクルを定める • PPUのtick関数に3倍したものを引数として渡す • cyclesが341を超えた時にscanlineをインクリメントし、 scanlineが241になった時にCPUにNMI割り込み命令 を送る • CPUはNMI割り込み命令を受け取ると現在の命令の実
行を終了し次フレームの画面の描写の準備に入る
スクロール 長くなるのでカット! ファミコンには画面の状態を保持する VRAMと呼ば リがあって、サイズは2 KiB。1画面を表示するのに モリは1KiBなので2画面分を割り当てられる。まず zero hit flagの設定をする。sprite
zeroを画面の特 置(X, Y)に配置し、sprite zero hit flagが0から1に と、CPUはPPUが[0..Y]スキャンラインのレンダリン しYスキャンライン上でXピクセルのレンダリングが ことを示す。垂直または水平ミラーリングを実装し viewportを動かしていった分を shift_x, shift_yとお 256-shift_x, 240-shift_yを2つ目の画面のサイズ 定しフレーム毎に更新することで、静的な背景を動
できたもの
まとめ • 当時、ファミコンの開発に携わってた人たちはほんとにすごい • エミュレータの実装を通して、少しだけでも当時のエンジニアたちの気持ちを理解することができた • メモリアクセスやアセンブラについて詳しくなれた • エミュレータ自作とは結局小さなコンピュータを自作すること。次は OS自作に挑戦したい。
• 最後まで完成させることはできなかったけど、今までやったことがない低レイヤなことができてよかった
おまけ セキュキャンに申し込みました。 今回の開発で低レイヤにもっと興味が沸いたので OS自作や探査機自作ゼミに参加したい。 5/20が応募課題の締切なので1日8時間ほど取り組めばなんとか終わるだろうという計算 ...