解析環境と開発環境が整ってきたので、少しまとまったプログラムを作ってみる事にした!
とは言ってもせいぜい半日頑張ったら作れる範囲に留めたい…。
おじさんは集中すると寿命が縮まっちゃうんだよ!(T-T)
というわけでいつものパターンで、絵をドット単位に動かす事をやってみた!
とりあえず動いた動画をTwitterに投稿したので見て欲しい。
CASIO AI-1000でキャラクタをドット単位に動かしてみた!
— PocketGriffon (@GriffonPocket) 2021年7月30日
ついでに背景も入れてみたよ(^^) pic.twitter.com/J5jhr0A1CZ
前回のブログで、麻雀牌を表示するプログラムを掲載した。
あのプログラムは縦方向の表示位置は8ドット単位しか指定が出来ない。これはAI-1000のVRAM構造に由来する制限だ。縦8ドット=1バイトの構造となっているため、バイト境界以外に絵を表示しようとすると、それなりに面倒なコードを組まないといけない。
過去にHC-88やPC-8201などで同じことをしているが、どれも面倒なコードを組むことで実現していた。
HC-88でプログラミング! その10 - レトロパソコンであそぼう!
↑6301CPUで挑戦した
HC-40でプログラム開発してみた その3 - レトロパソコンであそぼう!
↑Z80でのドット単位描画
今回もこのパズルのようなプログラムを組んでみよう!
ドットをずらす方法を検討
一番コアとなる処理は画像データをシフトするところだと思う。ここの構造がきっちりと決まると、その周りのコードはワリと流れで組んでいけるw
基本的な考え方は「縦16ドットのデータをレジスタに載せておき、必要回数分をシフトしながらはみ出たドットを別のレジスタで拾う」だ。
そのため、レジスタが多いマシンでは意外にも簡単に実装が出来る。
HD61700はレジスタが超豊富にあるので、アルゴリズムにこまる事は何もなかった!
メインレジスタに16ドット分のデータを入れておき、bidwでシフト、はみ出たビットをrodで拾う。
bidw $0
rod $2
これで(AI-1000の場合は)1ドット下にずれる。
これを最大7回繰り返す事ですべての位置に描画する事が可能になる。
あとはすでに描画されている絵と合成するために、VRAMのデータとマスクパターンでANDして、ORで書き込む。この辺りは1980年代からの有名な手法なので聞き覚えがあるはずだ。
動画を見てくださった方はわかると思うが、それなりの速度で動いてる。あれはリアルタイムに画像データをずらしながら表示している。高速化も全くしていないので、HD61700に慣れた人が最適化をすれば、倍以上の速度になるんだと思う。
当たり前だけど、最初から一発で完成するプログラムが書けるわけではない。でも私の場合は、まずはバグありでも構わないから一通り組み立ててしまう。その後、機能を絞って(例えばX=0、Y=1、牌=0のようにY以外は特殊な事をしないとか)確実な部分を1つずつ組み上げていく手法で進めている。
上の写真は、ようやくドットをずらした状態で表示が出来るようになったところ。ちゃんと下にある牌と重ね合わせも出来るようになっている。
重ね合わせ処理を入れた副産物として、背景を入れる事も出来た。これは上手に背景と重ね合わせてるというよりは、背景でVRAMを消去、その上に牌を描いているだけだ。
HD61700で気がついたことトカ
初めてHD61700でプログラムを組んでみたが、いくつか気がついたことがあったのでご紹介してみたい。多分、HD61700に慣れた方ならば「そこでハマる?」って思うのかもw
キャリーを含む加算は?
キャリーフラグを含む加減算命令が無いような気がする…。Z80風で言うところの「ADC/SBC」命令が存在しないっぽい。今回のプログラムで困る事は無かったが、Z80に慣れた人がHD61700を使うと面食らうかも。
同じくサインフラグも無いので要注意。
インデックスレジスタの加算
IXレジスタを加算する方法、例えば8を加算する時は…
gre ix,$0
ldw $2,8
adw $0,$2
pre ix,$0
というように書いていたが、以下の方法を使うと楽ちんだと気がついた。
ldi $0,(ix+7)
$0にはダミーの読み込みが入るが、それ以外のレジスタは壊さない。
PUSH/POPのワナ
2バイトのPUSH/POPは注意が必要だ。
例えば、$0と$1を16ビットデータとしてPUSH/POPする時には以下のように書くらしい。
phuw $1 ← PUSH
ppuw $0 ← POP
そう、指定するレジスタ番号が違うのだ!これはわかる前もハマり、理解した後も何度もハマってしまった!ワタシ的には鬼門の命令に認定(^^;;
ブロック転送のレジスタ
これも何度書いても慣れていないんだけど、bup命令でのレジスタの設定。
なんとなく「転送元アドレス、転送先アドレス、転送バイト数」と指定したいところだけど、HD61700の場合は「転送元先頭アドレス、転送元の最終アドレス、転送先アドレス」と指定する。慣れの問題だろうけれどもクセがあるなと感じた命令(^^;;
HD61700のプログラムを組み初めて2日でここまで作れたのは、やはり先に逆アセンブラなどを作って命令そのものに慣れ親しめた事が大きいと思う。どんな命令があったのか、おぼろげに覚えてるからね!(それでも4ビットシフト命令の事は忘れてたけど汗)
AI-1000でのプログラム挑戦も、私の中ではそろそろ終わりに近づいてきた!
あと2つほどやってみたいことがあるけれども、時間がかかる事なのでどうしようかなーと悩み中(コンパイラじゃないよ!)
ではまた次回!(^-^)ノ