コマンド入力
目次
6502 基本
実は、6502 のプログラムを先に作り、Z80 基本のプログラムはそれを移植したものです。
データが 256 バイト境界にかからないようにする、などの仕様もそのため。
LDA #<COM1 ; 2
STA >1 ; 3
LDA #>PADHIST ; 2
STA >2 ; 3
LDA #<PADHIST ; 2
STA >3 ; 3
LDX #3 ; 2
LOOP:
LDA COMTABLE-1,X ; 4
STA >0 ; 3
LDY LENTABLE-1,X ; 4
LOOP2:
LDA (0),Y ; 5
CMP (2),Y ; 5
BNE BAD ; 3 / 2
DEY ; 2
BNE LOOP2 ; 3 / 2
HIT:
TXA ; 2
BNE END ; 3 / 2
BAD:
DEX ; 2
BNE LOOP 3 / 2
LDA #0 ; 2
END:
COMTABLE:
DB >COM3,>COM2,>COM1
LENTABLE:
DB 6, 4, 4
COM1:
DB $80,$01,$05,$04
COM2:
DB $40,$01,$04,$05
COM3:
DB $80,$40,$40,$40,$01,$01
ゼロページの >0 >1 に COM1~COM3 へのポインタが入ります。
また、>2 >3 に PADHIST へのポインタが入ります。
ループカウンタは、外側と内側でそれぞれ X と Y 。
ループカウンタ Y はインデックスとしても使われますが、減算していくため、Z80 版とコマンドの比較順序は逆になります。
全体の前処理(LOOP まで)に 17クロック。
内部ループの前処理(LOOP~LOOP2)に 11クロック。
内部ループ内は、データバイトが不一致だと 13 クロックで、一致すると 17クロック。ただし、最後の1バイトの処理は1クロック速くなります。
後処理は、不一致時も、一致時も 5クロック。
Z80 と同じように繰り返し回数などを当てはめると…
17 +11*3 +13 +17+13 +17*6-1 +5*2 +5 = 209
総計は 209クロックです。
速度判定
6502 は 209 クロック。周波数を考慮して倍にすると、MSX での 418クロック相当の実時間になります。
Z80 は 705クロックなので、差は287クロック。ファミコンが4割ほど速いです。
問題の本質が「メモリ内を検索する」ことなので、メモリアクセスが遅い Z80 にはかなり不利な問題。
さらに、Z80 のレジスタに入りきらないほどのパラメータが必要になる…つもりで問題を設定したのですが、裏レジスタまで使えば入りました。
特殊な形の文字列検索なのでボイヤー・ムーア法の応用をすれば速くなるかもしれません。
といっても、例題では Z80 の例で、「1番目が1文字だけ一致して失敗したから、2番目は処理をスキップし、さらに3番目の1文字目は比較済みの状態から始める」と言うプログラムを組むのが関の山。プログラムが複雑になる割にどの程度高速化されるかは試してないのでわかりません。
パッド関連3題では、ちょっと Z80 不利な問題にしすぎた感じ…特に、コマンド入力は当時のゲームではあまり見られませんでしたし、遅いから性能が悪かった、と言うわけではないかな。