Video 実装
座標系統を修正
Y 座標関連は tilemap の上端のアドレスなり、スプライトの上端の場所を算出すると 0x80 を上端とすると無駄な加減算が発生しないことはなんとなく気づいていた。スキャンライン割り込みでも可視領域上端は 0x80 ベースなのでこれを機会にいろいろ修正。
一応下記の Y 座標系統にした。0x17f の次を 0x6c にする方法もあるんだけどどっちのが最善なのかは不明。
0x070 reset 初期値 (*1) 0x080 可視領域上端 0x17f 可視領域下端 0x180 vblank start, DRAM refresh start 0x19b vblank last (0x19b の次は 0x080) 0x080 可視領域上端 *1 シミュレーションで 0x10 ラインの余裕を作るだけ
X 座標も 0x40 を左端とすると、わりと都合がいいんだが tile のラインバッファのレンダリング回数が増える。設計を見る感じ、仮想領域の左端から全て書いているようだが、内蔵 RAM 容量も関係してくるので可視領域(-1チップ)から書くようにしているために、加減算の場所がかわっただけで回路規模はあんまりかわらない模様。
スキャンライン割り込み
何度か書いているが、任意の場所でスクロールレジスタを変更するためにこの割り込みがある。普通の設計ではスクロール専用RAMを設けるのでこんな割り込みはいらない。(家庭用ゲームハードでのテクニックにロマンを感じる人がいるが、そういう理由ではない)
これを対応させないと見た目が悪いし、ちゃんと動いているか確認できない。ソフトを見たら、割り込みが来たら RAM のデータを書くだけになっている(それが無難で普通)のでこれをパラメータにする。
def scroll_dump(filename) buf = File.open(filename, 'rb').read.unpack("v*") f = File.open("scroll.nh", "w") s = sprintf("#define INTERRUPT_LINE 9'h%03x", buf[0x23bc / 2]) f.puts(s) d = [] d << buf[0x23b6 / 2] d << buf[0x23b2 / 2] d << buf[0x23be / 2] d << buf[0x23ba / 2] d << buf[0x23b8 / 2] d << buf[0x23b4 / 2] d << buf[0x23be / 2] #変更無しなので同じ d << buf[0x23ba / 2] ["VBLANK", "RASTER"].each{|type| [0,1].each{|layer| ["Y", "X"].each{|axis| s = sprintf("#define %s_TILE%d_SCROLL_%s 9'h%03x", type, layer, axis, d.shift & 0x1ff) f.puts(s) } } } f.close end
そこらへんをみてたらどうもスクロールを変更するライン-1に割り込みがかかるようになっている。CPU レジスタとスクロールレジスタを別にしてスキャンライン更新時にCPUレジスタを取り込むような形にしないと、ファミコンみたくちらちらすると思う。
ここらへんがちょっと難しくてそのパラメータをどこから取り込むのが難しい。カプセル化を進めたので Video の外から書き込むタイミングを把握しづらい。
sprite を直した
過剰にスプライトが出てしまう問題の原因は下記らしい。ここでいう offs += 4 になっていた。
offs = 0; while (offs < spriteram_size/2) { (中略) w = 1 << ((m72_spriteram[offs+2] & 0xc000) >> 14); (中略) offs += w*4; }
横幅の分はそこに書いた分の sprite attribute が無視されるみたい。1のシフト回数を変数(配線)にするといろいろスマートに記述できるんだが、ハード的にシフト回数任意はあまりよくないような...
NSL core から warning がでるんだが、ここだけは見逃すことになった。というわけでかなり綺麗に絵が出始めている(スコアとゲーム部のスクロールレジスタの更新が1ライン早いけどあとで直す)。
makefile を作り直した
ここまでで結構長いので次回に書くと思う(といって書いていないことが多いですけど)