Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Common Lispでのゲームボーイエミュレータ実装進捗報告 vol.1
Search
t-sin
March 31, 2022
Programming
0
840
Common Lispでのゲームボーイエミュレータ実装進捗報告 vol.1
Shibuya.lisp lispmeetup #102
で発表したときの資料です。
t-sin
March 31, 2022
Tweet
Share
More Decks by t-sin
See All by t-sin
Lispの紹介 〜 令和最新版
tsin45
0
660
Carp言語さわってみた 〜鯉を取り戻せ編〜
tsin45
0
1.2k
Common Lisp製のゲームエンジンTrialについてすこし
tsin45
0
1.2k
Other Decks in Programming
See All in Programming
その面倒な作業、「Dart」にやらせませんか? Flutter開発者のための業務効率化
yordgenome03
1
130
登壇は dynamic! な営みである / speech is dynamic
da1chi
0
340
3年ぶりにコードを書いた元CTOが Claude Codeと30分でMVPを作った話
maikokojima
0
340
AIと人間の共創開発!OSSで試行錯誤した開発スタイル
mae616
1
460
他言語経験者が Golangci-lint を最初のコーディングメンターにした話 / How Golangci-lint Became My First Coding Mentor: A Story from a Polyglot Programmer
uma31
0
170
kiroとCodexで最高のSpec駆動開発を!!数時間で web3ネイティブなミニゲームを作ってみたよ!
mashharuki
0
540
iOSエンジニア向けの英語学習アプリを作る!
yukawashouhei
0
200
Introducing ReActionView: A new ActionView-Compatible ERB Engine @ Kaigi on Rails 2025, Tokyo, Japan
marcoroth
3
1k
オープンソースソフトウェアへの解像度🔬
utam0k
15
2.9k
なぜあの開発者はDevRelに伴走し続けるのか / Why Does That Developer Keep Running Alongside DevRel?
nrslib
3
410
AI Agent 時代的開發者生存指南
eddie
1
1.2k
Server Side Kotlin Meetup vol.16: 内部動作を理解して ハイパフォーマンスなサーバサイド Kotlin アプリケーションを書こう
ternbusty
3
190
Featured
See All Featured
The Invisible Side of Design
smashingmag
302
51k
Thoughts on Productivity
jonyablonski
70
4.9k
GraphQLとの向き合い方2022年版
quramy
49
14k
Being A Developer After 40
akosma
91
590k
A better future with KSS
kneath
239
18k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
1.6k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Building Applications with DynamoDB
mza
96
6.7k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
What's in a price? How to price your products and services
michaelherold
246
12k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
285
14k
Transcript
TTERY DOT MATRIX WITH STEREO SOUND Common Lispでの ゲームボーイエミュレータ実装 進捗報告
vol.1 @t-sin 2022-03-31 Lispmeetup #102
TTERY DOT MATRIX WITH STEREO SOUND もくじ • 発表の目的 •
実装の動機と目的 • ゲームボーイについて軽く • エミュレータ実装について軽く • 実装の方針 • 実装日記 vol. 1 • 実装の現状 • まとめ
TTERY DOT MATRIX WITH STEREO SOUND 発表の目的 • エミュレータ実装の進め方を伝えたい –
エミュレータ自体の最も基本的な構造 – とっかかりとなるドキュメント – 動作テストのための情報 • エミュレータ実装の雰囲気を伝える – 現在進行形で開発しているライブ感 – 試行錯誤のようす • 実装の現状を話すことでやる気を生成する
TTERY DOT MATRIX WITH STEREO SOUND 実装の動機 〜 建前 •
エミュレータのしくみが知りたい – Wii U/3DSのバーチャルコンソール – QEMU – Virtual Box • ゲームボーイについて知りたい – どんなハードウェアだったのか – なにができる/できないのか – ゲームボーイのソフトウェア開発の足がかり
TTERY DOT MATRIX WITH STEREO SOUND 実装の動機 〜 本音 •
ファンタジーコンソールを考える足がかり – 架空のゲームコンソールのエミュレータのこと – PICO-8とか有名 – Common Lisp製のlambda8ってのもある • https://github.com/raydeejay/lambda8 • すき – はじめて持ったゲーム機なので – レジェンドなハードウェアなので – ゲームボーイの音楽がすきなので – 『星のカービィ2』…!!!
TTERY DOT MATRIX WITH STEREO SOUND 実装の目的 • エミュレータ実装の勘所を得る •
エミュレータ実装にCommon Lispが活きるか調べる • エミュレータのCommon Lispにおける形を模索する • 既存のゲームボーイ向けソフトウェアを動かす – Little Sound DJ: GBを作曲・演奏環境にする – 『星のカービィ2』…!!!!!!!
TTERY DOT MATRIX WITH STEREO SOUND 概説: ゲームボーイ (1) •
1989年発売の携帯ゲーム機 • 緑がかったモノクロ液晶、ピコピコ音源 • みんなも知ってるあのソフト – 『星のカービィ』『ドクターマリオ』『ゼルダの伝説 夢を見る島』『ポケモン赤緑』 • 後にいくつかのバリエーションがでる – モノクロ液晶: GBライト、GBポケット – カラー液晶: GBカラー – 次世代機: GBアドバンス
TTERY DOT MATRIX WITH STEREO SOUND 概説: ゲームボーイ (2) •
ハードウェア仕様 – CPU: Intel 8080に似たカスタムCPU – ROMカセット: 256Kb ~ 32Mb – RAM: 8Kb – Video RAM: 8Kb – メモリマップドI/O • 本体に入ってるペリフェラル – モノクロLCD (4階調、160x144) – SSG(Software-controled Sound Generator)音源およびスピーカー – 入力関連デバイス (十字キーとかAボタンとか) • ソフトウェアおよびカセット – 挿したカセットのROMはメモリの0x0000から0x7fffにマップされる
TTERY DOT MATRIX WITH STEREO SOUND ゲームボーイ関連リソース集 • Pan Docs:
https://gbdev.io/pandocs/ – GBのハードウェアの構成や仕様が書かれてる – エミュ開発するならまずは読みたい – ぼくの理解は基本PanDocsでできています • Opcode table: https://www.pastraiser.com/cpu/gameboy/gameboy_opcodes.html – GBのCPUの命令テーブル – PanDocsの命令一覧は具体的なバイナリが書かれてないので • Awesome List: https://gbdev.io/resources.html – GB関連キュレーションリスト – docリンクや開発ツール、GBのFLOSSなソフトなど • Gb-docs-ja: https://github.com/pokemium/gb-docs-ja – いま見つけたけど日本語のドキュメントあった – Pan Docsあたりがベースっぽい
TTERY DOT MATRIX WITH STEREO SOUND エミュレータ: 基本 • エミュレータ
– ある計算機システムの動作を再現するソフトウェア • 計算機システム – CPUとメモリと周辺機器(とバス) • エミュレータ実装 – CPUがバスを通じてメモリや周辺機器と起こす相互作用をプログラムで再現 • 相互作用のキーパーソンはCPU 1. CPUがメモリから命令を読む 2. CPUが命令に対応した処理を実行する 3. 1に戻る
TTERY DOT MATRIX WITH STEREO SOUND エミュレータ: 実装方針 • まずCPUの動きを(不完全でも)実装する
– あとメモリ • 周辺機器(画面、音、入力)は後からやる – I/Oはメモリを介するのでCPUとメモリが必要 • システムの起動プロセスは再現しなくてよい – ピローンはいらない • 初めてなので愚直にやる – エミュレータ自作はじめてなので – 勘所まったくわからないので – 早すぎる最適化・抽象化をしない
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (1) •
レジスタを定義する – 基本は16ビット – 8bit幅でも使える • レジスタのアクセサを定義 – 全レジスタに同じことするのでマクロ書く • https://github.com/t-sin/lambdaboy/commit/ 28d34885f3cb564386b1cb23bc34b43acdc99ef4 ;; レジスタ定義 (defstruct register (af 0 :type (unsigned-byte 16)) ... (sp 0 :type (unsigned-byte 16)) (pc 0 :type (unsigned-byte 16))) ;; レジスタアクセサをマクロで生成 (make-accessors af)
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (2) •
メモリを定義する – メモリマップ • 領域を二分木としたい • でもまずは愚直に領域の配列とする – メモリアクセサ • getter/setterをマクロで生やす • https://github.com/t-sin/lambdaboy/commit/ 8b60adcfb4c2b0e1d3c0d6242d88266121c370d0 0x0000 ~ 0x3fff カセットROM #1 0x4000 ~ 0x7fff カセットROM #2 0x4000 ~ 0x7fff カセットROM #2 0x8000 ~ 0x9fff Video RAM メモリブロック メモリ全体 →メモリブロックの配列
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (3) •
CPUを定義する • 空のCPUループをつくる (defstruct gameboy (register (make-register) :type register) (memory (make-memory) :type memory)) (defun start (gb) (loop ;; (execute-1 gb) ← あとで実装する ))
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (4) •
レジスタを初期化する – 電源ON後、どこにPCがセットされるか • 起動時、PCは0x1000 – initialize-gameboy関数をつくって初期化しておく • 1個の命令実行処理を書く – 命令データをメモリからフェッチ – 命令データをデコード – オペコードに合わせて分岐し実行 (defun execute-1 (gb) (let* ((b (fetch-byte gb))) (case b (<バイト値> 処理…) (t (error "unknown instruction: ~x" b)))))
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (5) •
「なにもしない」NOP命令の実装 – オペコード分岐のところに追記 • NOPのみのプログラムを実行可能にする – 「メモリにプログラムを置く」 • 単にメモリを0初期化しておく – CPUループで1命令実行関数を呼ぶ • 無限ループ成功!! (defun execute-1 (gb) (let* ((b (fetch-byte gb))) (case b (#x00 (vom:debug "op: NOP") nil) (t (error "unknown instruction: ~x" b))))) (defun start (gb) (loop (execute-1 gb))) ; ←コメントアウトはずす
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (6) •
ROMファイルを読み込む処理の実装 – ROMファイルを開く – 先頭からメモリに書き込む • 適当なROMファイルをもってきて実行してみる – 動作確認用ROMとしてBlagg’s test ROMsを用いた • https://github.com/retrio/gb-test-roms • 命令の機能テストからハードウェアの挙動的なテストまで、いろいろカバーしてる • /cpu_instrs/individual/06-ld r,r.gb: ld命令のみをテストするROM • NOPしか実装してないのでエラーになる • しかしながら実際のROMを実行できた!!!
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (7) •
命令実装をひたすら繰り返す: – テストROMを実行する – 未知の命令だよエラーがでたらその命令を実装する – 最初にもどる • 命令を実行するたびにログを吐かせる – 無言だとなにが起こってるかわからぬ – [PC: 0xXX SP: 0xXX] op: 0xXX: OP REG のような感じ – 実行されてる感が得られテンション爆上げ
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (8) •
そうやって実装していったところ… • なんだか無限ループはしてる気がする – 対象テストROMは結果を画面に表示するっぽい • ので正しい可能性がある • 何を描画しているかわからないので描画内容を見たい – 描画のしくみ無知なので別の手で表示を確認したい
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (9) •
テストROMはソースコードが公開されているので 実行ログとソースコードを突き合わせて違ってる箇所を探る – テストROMはアセンブリで書かれている – ありがとうc-lesson (https://karino2.github.io/c-lesson/) • このあたりまではちゃんと実行されてそう – https://github.com/retrio/gb-test-roms/blob/master/cpu_instrs/source/common/runtime.s#L96 – 表示系サブルーチンのための初期化処理を呼ぶところ • 文字表示サブルーチンへのCALLを捕捉してみる – 特定アドレスへCALLしたらオペランドの文字を(format t “…” ...)して確認 • 特定アドレス: 文字表示コードの開始アドレス • 実際は文字表示サブルーチンに飛んできてなかった…
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (10) •
実際は文字表示サブルーチンに飛んできてなかった… – なぜ… • ところで全ての命令がログにでるので何がわるいかわからぬ – PCがある値になったら処理を実行 • PCが表示初期化処理にきたらログをONにしたい – ブレークポイントとフック的なものを実装する – ところで最近gdbと戯れていますが、そういう機能ほしい • 文字表示初期化処理をCALLした時点からログ表示を開始する – それ以前はログ無効
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (11) •
初めてのRET命令の戻り先が1byte違うことが原因 – テストROMのソースコードと実行ログを目diff – つまり正しい無限ループではなかった • 分岐命令(JP, CALL, RET)でPCの扱いがよくないっぽい – PCなにもわからない(´・ω・`) • 現在の実装の問題点: 命令の処理が関数になってない – オペコードごとに処理を重複して書いてた • コピペミスやtypoで命令の本体がパラレルワールドになってた – PC進める量もついでに異なってたりした
TTERY DOT MATRIX WITH STEREO SOUND 実装日記 vol.1 (12) …
現在 • 命令の本体を関数化 – 粛々とやっている – さらば、冗長クソデカecase式 • やる気の低下 – 未実装の命令まだまだたっくさんある – よくわからぬ壊れかたするので地道 • OpenGLでテクスチャ描画を試す気晴らし – ゲーム画面やウィンドウを表示するテスト – 最終的な画面状態をテクスチャに書き込んで描画する予定 – https://github.com/t-sin/lambdaboy/blob/05d3c43233e73488eef483beb32cd0879b425df0/ window.lisp
TTERY DOT MATRIX WITH STEREO SOUND 現時点での考察・反省 • GOOD: ROMを実行して未知命令を実装する方法はよい
– 実装済み命令が増えると先まで動くのできもちよい • BAD: PCがどこを指すべきかは混乱があった – GBのCPUは1byteまたは2byteのため – 理解が不明瞭なまま進めたため分岐命令のバグを生んだ • BAD: テスト書いてなかった – モチベの維持を最優先したためTDDはしなかった – TDDではないとしても命令を組み合わせたときの挙動はテストで確認しておくべき • PROBLEM: デバッガほしいなァ… – ステップ実行、シンボル情報の利用、レジスタの内容表示… – GDBのTUIモードがすてきなので、そういうのほしい…
TTERY DOT MATRIX WITH STEREO SOUND 今後は • 粛々と実装をすすめていく •
描画まわりのドキュメント読む • Common Lisp-wayを模索する – SLIMEによるデバッグやステップ実行? • やる気を醸成していく – ちなみに: 発表資料を書くだけでも現状が整理されてだいぶモチベが復活してきた • そしてvol.2へ…
TTERY DOT MATRIX WITH STEREO SOUND まとめ • エミュレータ実装するときに必要な知識を述べた –
くそ雑・計算機アーキテクチャ – ゲームボーイ自体の情報 – 実装に必要な・知っておくとよい情報 • エミュレータ実装の現時点の進捗を述べた – https://github.com/t-sin/lambdaboy • エミュレータ実装の今後の方針を考えた • エミュレータ実装の雰囲気とライブ感を伝えた(かった) – つたわった? – 懇親会でツッコミや感想ください