遅い!

デモは、かなり速い動きをするのに、ゲームになると、REM君、もっさりとしか動かないので、こりゃ、どっか高速化しないといけないかも。

……と、いうことで、ちょっとだけ、高速化してみました。

デモとゲームの大きな違いは、キー入力処理と、最上段のステータスの表示です。

キーについてはあまりいじる余地もなさそうなので、ステータスの表示に関して考えてみます。

基本的には文字列を表示しているだけなのですが、文字の表示には、VRAMのY方向の変位を計算するのにx320をしています。また、面数と残フルーツは、数値を文字に変換しています。この二つをちょっとやっつけます。

x320は、16bit addを9回繰り返して99サイクルで計算していますが、これを、あらかじめ用意したテーブルを参照することでさぼり55サイクルと半分ほどに詰めました。

    add hl,hl
add hl,hl
add hl,de
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl

これを、以下のようにします。vram_y_oosetには16bitで、0,320,640,...と0-24に対応するオフセットを書き込んでおきます。

	add		hl,hl
ld de,vram_y_ofset
add hl,de
ld e,(hl)
inc hl
ld h,(hl)
ld l,e

数値の変換は、Aレジスタの値を、二けたの10進数として、4bitずつAレジスタに設定します。100を超えていたらキャリーフラグを立てて戻ります。分岐やループを作らないために、0~187までしかサポートしません。面数は0-99だし、フルーツ数は最大159(コンストラクション中は160)なので、問題ありません。

元のコードはループしたり分岐したりしていたので、かなりましでしょう。DAAなんて、何に使うんだという命令でしたが、なるほど、こういう限られた値の変換ではかなり便利。

        push    hl

ld h,a
and 0fh
or a ; clear HF
daa
ld l,a
ld a,h
and 0f0h

rrca
rrca
rrca
rrca
daa

add a,a
daa
add a,a
daa
add a,a
daa
ld h,a
add a,l
daa
add a,h
daa ; set CF if over 100

pop hl
ret

ただ、Hフラグの立つタイミングが分からず最初は結構トラブりました。AND 0FHで下1nibbleを取り出したとき、Hフラグが立ちDAAで0-9の値でも+6されてしまい、おかしなことに。結局、直後にOR Aを挿入して、Hフラグを強制クリアして事なきを得たんですが。

最後のDAAでキャリーが立つように演算順序をひっくり返しているのですが、これが187で頭打ちになる理由で、188の時には、最後のDAAの時には桁あふれせず(その前のDAAであふれ済み)、188ではなく88になtってしまうのです。まあ、この値は出てこないので、この場はよしとしますが、まじめにやろうと思ったら更なる工夫が必要です。

以上に点を修正したら、まあ、妥協可能なくらいに速度が改善しました。ま、パズルなのでそこまで速度は気になりませんが16x10マスのフィールドを移動するので、遅すぎないに越したことはありませんからね。

尤も、QUASI88の上で動かしているリファレンスとしてのPC-8001版は随所にウェイトが入っているにも関わらず、速すぎるくらいに速いんですけれどね……。