Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
ファミコンに思いを馳せる〜エミュレータ自作を添えて〜
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
noharu36
December 01, 2025
Programming
41
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ファミコンに思いを馳せる〜エミュレータ自作を添えて〜
noharu36
December 01, 2025
More Decks by noharu36
See All by noharu36
皆さんはHaskellをご存知です_しかし皆さんはHaskellが読めません_.pdf
noharu36
0
50
検証!会津は本当に地盤が硬いのか?
noharu36
0
38
自作オブジェクトストレージをRustで
noharu36
0
82
shell自作した話
noharu36
0
37
Rustを布教したい
noharu36
0
50
neofetchよ、永遠に
noharu36
0
41
ISSの軌道計算をRustで
noharu36
0
36
Other Decks in Programming
See All in Programming
Heart of Swift Concurrency
koher
0
910
Security issues being discussed on Web Platforms
petamoriken
0
980
更なる可用性を求めて、5年間運用したKotlinのアプリケーションをGoでリプレイスする話
ken_tunc
0
300
Family mrubyの進捗
kishima
1
130
新卒PdEのリアル
ryu1013
1
500
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
2.8k
変化を抱擁するドキュメントの作り方 - ビジネスルール駆動開発がもたらす、コードとの新しい関係
ioki
2
220
iOSDC2026登壇資料.pdf
riofujimon
0
170
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
620
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
7.5k
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
220
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
1
290
Featured
See All Featured
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
65k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
360
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
810
4 Signs Your Business is Dying
shpigford
187
23k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
520
Designing for Timeless Needs
cassininazir
1
480
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
470
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
Mind Mapping
helmedeiros
1
360
[RailsConf 2023] Rails as a piece of cake
palkan
59
7k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
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時間ほど取り組めばなんとか終わるだろうという計算 ...