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
noharu36
December 01, 2025
Programming
46
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
54
検証!会津は本当に地盤が硬いのか?
noharu36
0
42
自作オブジェクトストレージをRustで
noharu36
0
89
shell自作した話
noharu36
0
41
Rustを布教したい
noharu36
0
58
neofetchよ、永遠に
noharu36
0
43
ISSの軌道計算をRustで
noharu36
0
44
Other Decks in Programming
See All in Programming
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
160
気持ちぃ〜角丸 Squircle
ryu1013
0
310
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
280
RAG の “R” を Swift で覗いてみる 〜「意味から探す」検索の仕組み〜
nao_randd
0
170
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
380
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
3
670
sbt 2.0: takeoff
eed3si9n
0
160
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
350
3回つくってわかった、 定期実行ジョブ基盤の本質情報
takai
0
510
Next.js: The final boss of Web Performance
guaca
0
280
Kotlinの15年とServer-Side Kotlin
n_takehata
1
150
iOS 27でニュースアプリはどう変わる!? 〜日経電子版の新機能対応と、開発事例から〜
lynnswap
7
13k
Featured
See All Featured
First, design no harm
axbom
PRO
2
1.3k
Ethics towards AI in product and experience design
skipperchong
2
440
For a Future-Friendly Web
brad_frost
184
10k
A better future with KSS
kneath
240
18k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
540
Code Review Best Practice
trishagee
74
20k
The agentic SEO stack - context over prompts
schlessera
0
970
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
77k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.6k
Raft: Consensus for Rubyists
vanstee
142
7.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時間ほど取り組めばなんとか終わるだろうという計算 ...