NES Emulator for PC-8801


img
6502 の理解を深めるために C64 界隈を流し読みしていたのですが
ふと思い立って未公開命令を実装してみることにしました。

6502 の未公開命令といえば「動作が不安定」とか CPU にあるまじき挙動をするようで
なかなかスリリングです。個体差があってマシンごとに違う結果が返ってくるんだとか。
(バスの状態に左右されるという説も)

ついでに PPU を適当に実装して 88 でついにマ○オが!え、既にある?



■ NES Emulator for PC-8801

NES Emulator for PC-8801 Series 20131006版 (D88とソースコード)
 ROMイメージなどは含まれません。あしからず。

ほぼ観賞用です。実用にはなりません。6502 エミュレータに未公開命令を実装した記念に作ったものです。

拡張 RAM 128KB を使うので Mx 系列かそれに準じたオプションが必要です。
動作対象のソフトは PRG-ROM が 16KB で CHR-ROM が 8KB のものに限ります。

NES のエミュレータで使われているフォーマットはヘッダが付いていたり
ROM が結合されていたりするので、そのままでは使えないと思います。

本エミュレータはディスクの指定位置から決め打ちで PRG-ROM と CHR-ROM を読み込みます。
nes88.d88 と makenes88.exe と ROM ファイルのあるフォルダに移動して、
コマンドラインから以下のようにディスクイメージに書き込みます。ファイル名は適当。

> makenes88 -prg MARIOprg.bin 
> makenes88 -chr MARIOchr.bin 

成功すれば nes88.d88 に ROM ファイルが書き込まれます(上書き)。

◆ 操作

・カーソルキーの上下で表示範囲を切り替えられます(2段階)。
・テンキーの8246が上下左右、「A」「S」がセレクト、スタート、「Z」「X」がABボタンです。1P側のみ。


■ 永遠に未完



エミュレータで動かす場合には、クロック周波数を上げても速度が変わらない場合があります。
vblank の周期も上がらないとダメな模様。

PPU はほどほどに手抜きしてあります。
88 側は 8 色しか使えないので、R 面と G 面を BG 専用にして 4 階調を割り当て、
残りの B 面をスプライト専用に割り当てています。色は白で固定。

スプライトは 8x16 モードや上下反転は未実装。かろうじて左右反転は欲しかったので
あらかじめビットを入れ替えた状態のテーブルを作って実現しています。

0 番スプライトヒットとか当然のように無し。

スクロール機能も実装していません。無理。

解像度は本来 256x240 なのですが、88 は 縦 200 ラインなので 40 ラインが可視範囲外になります。
カーソルキーの上下でこの可視範囲を切り替えられるようにしてあります。
横解像度は 2 倍に引き延ばしています。テーブルで 2 倍のビットイメージに変換してから表示しています。

BG は更新されたところだけ書き換える方式なのですが、ネームテーブル 4 つに対し更新テーブルは 1 つなので変になるかも。
スプライトは全部毎回書き換えます。ドット単位の動きは 8x8 単位に変換しています。

$2002 は毎回 vblank を返します。というか、そうしないと起動しなかった。
NMI は 88 側の 8 フレームに 1 回起動するようにしています。
これを少なくすると画面更新頻度が上がる代わりに CPU エミュレーションがおろそかに、
逆にすると CPU エミュレーションにかかりきりになります。

未公開命令実装記念とか言っていますが、そもそもマ○オは未公開命令を使っていません。

スプライトを持ったマシンとかキャラジェネのあるマシンならもう少し違った表現ができたかな?
どうせ色数制限が付くならモノクロ GB という手もあるのですが、アレはアレで
メモリ空間がやたら広かったりいろいろ大変なので。でもいつか書きたいなぁ。

メモリマップとか。

88側 MAIN_RAM
0000-7FFF : NES RAM(0000-07FF)
          : NES PPU(2000-2007)
8000-BFFF : 本体・エミュレータ
C000-FFFF : VRAM

88側 EXT-RAM BANK#0
0000-7FFF : NES PRG ROM(8000-FFFF)
            16KB ROMは後半(C000-FFFF)なので 4000-7FFF に配置 

88側 EXT-RAM BANK#1
0000-1FFF : NES CHR ROM(0000-1FFF)
2000-7FFF : PPU-RAM(ネームテーブル他)

スプライトの内部バッファなどは本体の方に統合。

ディスク使用状況
track.0  sector.1- : ipl
track.1  sector.1- : 本体
track.9  sector.1- : NES-PRG 
track.17 sector.1- : NES-CHR

88でもちゃんとしたものを作りたい気持ちはあるんですが、環境が…。
昔は実機+紙上デバッグで当たり前にやっていたのが信じられないです。
その頃の効率で今やるのは流石に無理があるんですよね。。。
今回のコレも随分苦労しました。


■ 更新履歴

2013.10.06 更新

・キー入力を実装。
・$2007 からの読み出しの挙動を修正(読み出しバッファを介するように)。これでデモ画面の動作がオリジナルと同じに。
・スタックポインタがズレていたのを修正。グラフィックが化けていたのはこれが原因。痛恨のミス。
・BG の更新時にオーバーフローしてしまっていたのを修正。CPIR の挙動を理解していなかったためタイルデータにまで誤爆していた。
・PPU 描画処理の僅かな高速化。CPU にも少しだけ手を加えたが誤差レベル。
 元の命令の 10倍以上時間がかかるので幾つかの命令で僅か数 clk 縮まったところで意味ナシ。
 一応、NES 専用あるいは NSF 版でもバンクを使わない場合の高速化候補はいくつかあるのだけれど、メンテしづらくなるのでパス。


▲ TOP