JS ででででででででででででで でででででで
JS でファミコンエミュレータを作った時の話
自己紹介• HN: さい • Twitter: @sairoutine
• サーバーサイドエンジニア• フロントエンドフレームワーク Mithril の普及に努めてます
ファミコン
のエミュレータを JavaScript で作る
※ エミュレータ・・・動作を再現したソフトウェア
FaithJS
DEMO
FaithJS
• ブラウザで遊べる NES エミュレータ• Web Audio と Canvas を使用• ROM データを読み込んで CPU を再現してる• 割りとちゃんと 60FPS 出る• http://sairoutine.github.io/faithjs/public/
動機
僕も OS とは何かを知りたい!
ファミコンアーキテクチャについて
概要
http://web.sfc.wide.ad.jp/~gucchan/docs/nesdev.pdf より引用
http://web.sfc.wide.ad.jp/~gucchan/docs/nesdev.pdf より引用
ROM の用意• ネットに落ちてるのはもちろん違法• 自分で吸い出す?• 有志が自作プログラムを公開してるので使わせてもらう• FaithJS は門真なむ様のゲームを使用させてもらって動作確認http://www.geocities.jp/littlimi/fc.htm• nestest というテスト用 ROM もあります
主な情報源• NesDevhttp://wiki.nesdev.com/w/index.php/Nesdev_Wiki• NES on FPGAhttp://pgate1.at-ninja.jp/NES_on_FPGA/index.html• ギコ猫でもわかるファミコンプログラミングhttp://gikofami.fc2web.com/
リファレンスだけでは実装イメージが全然湧かない!!!
既存のエミュレータコードを読むWeb NEShttps://github.com/peteward44/WebNESJavaScript FC エミュレータhttp://twoseater.hp2.jp/nes/index.htmlbjnehttps://github.com/tanakh/bjneCycloahttps://github.com/ledyba/Cycloa
未解析部分も多々あるので実装が正!
事前知識• CPU
• OS
• メモリ• アセンブラ• バイナリ• 英語
レジスタ
• 8bit しかない•自由に使えるレジスタは A
X Y の3つ
描画の仕組み
http://web.sfc.wide.ad.jp/~gucchan/docs/nesdev.pdf より引用
6502 アセンブラの命令
ここからやっと JS の話!
すごい大雑把な処理の流れvar opcode = this.Get(this.PC++);
this.CPUClock += this.CycleTable[opcode];
this.PpuRun();
this.ApuRun();
this.ExecuteOpCode(opcode);
オペコードの実装NES.prototype.ExecuteOpCode = function (opcode) {
switch(opcode){case 0xA1://LDA XINDthis.LDA(this.GetAddressIndirectX());break;case 0xA5://LDA ZPthis.LDA(this.GetAddressZeroPage());break;
以降、 Switch 文が命令の数だけ延々続く
処理の遅い演算は事前に全パターン演算しておいてキャッシュするthis.ZNCacheTable = new Array(256);this.ZNCacheTable[0] = 0x02; // 0b0010var i;for(i=1; i<256; i++) {
this.ZNCacheTable[i] = i & 0x80;}
これで 60FPS!
まとめ
NES を実装するのはいいぞ!
NES を実装すると良いこと• CPU の知識が得られる (6502 だけでなく、
8086 や i386, x86_64 にも興味関心が出てきた• アセンブラに興味関心が出てくる! ( 例えばある処理が重い軽いの話に、アセンブラレベルで処理が追えるようになる )• 英語が読めるようになる! ( 有志のリファレンスはほぼ英語なので )
みんなもやってみよう!
ありがとうございました