PC-6001mk2は GVRAMのトップアドレスをAtrbエリア、+$2000の位置をGrphエリアとした2プレーンで構成されています。そのため、AtrbエリアとGrphエリアをどちらも消去しないと、正しく消すことが出来ません。先程のプログラムですが、最初に Atrbエリアを消去しようとしています。

.lpAtrb REPT 4 ld sp, hl ; SP コピー元 pop de push de add hl, bc ENDM

HLに消去対象アドレスが入ってるのでSPに値を反映します。次にPOPとして、カートリッジのRAMから消去データを取得します。即座にPUSHして、今度は本体メモリのGVRAMに対して書き込みを行います。次の行にADD HL,BCとして更新して、それを4回繰り返します。

今まではアドレスを下げて来ましたので、次はアドレスを上げるためオフセット値が格納されているBCの値を符号を反転した値にします。そして、次のGrphは+$2000の場所ですから、SET5,Hとして+$2000と同等の計算としています。

ld bc, -VRAM.WIDTH set 5, h

ここまでは特に大きな問題はありませんが、問題は次の Grphの消去処理です。

.lpGrph REPT 4 ld sp, hl ; SP コピー元 pop de push de add hl, bc ENDM
Atrbと全く同じ処理を記述しています。HLの値をSPに反映してますが、この時のHLの値は何処なのでしょうか。Atrbを消去する際に本来消す範囲の更に1ライン下にズレています。その場所から消去を開始していますので、Grphの消去範囲が1ライン全体に下にズレています。これがバグの原因です。簡単な直し方としては、Grphの処理は先にアドレス計算をしてしまうという方法があります。

.lpGrph REPT 4
add hl, bc ld sp, hl ; SP コピー元 pop de push de ENDM

これで正常動作になります。なお、AILZ80ASMなら、最後のオフセット計算を無しに出来るため、以下のような記述がベストな答えとなります。

※ 私が今現在使用しているクーラーがコレ。平時は本当にこれ動いてるのって疑問に思うほどに静音です。CPUに負荷を掛けると元気よく回りますが、騒音という程ではないかな。少しだけお高めですが、こちらを買って良かったと今でも思っています。

;----------------------------------------------------------------------- ; 横16ドットキャラを消去する ; HL 消去アドレス
; EraseChara16x4: di ld (.stack), sp ld bc, +VRAM.WIDTH .lpAtrb REPT 4 LAST -1 ld sp, hl ; SP コピー元 pop de push de add hl, bc ENDM ld bc, -VRAM.WIDTH set 5, h .lpGrph REPT 4 LAST -1 ld sp, hl ; SP コピー元 pop de push de add hl, bc ENDM
.stack equ $ + 1 .exit ld sp, 0 ; SP 元に戻す ei ret