HC-88でプログラミング! その9

長かった6301CPUへの道

やっと…ようやくここまで来た!(感涙

HC-80の資料を手に入れて「へー、サブCPU側にプログラムを送れるなんて、FM-7みたいで面白い!ぜひやってみたい!」と思ったのが1年以上も前の事。何せその時はまだHC-80を手に入れてなかったから(^^;; 結構なレアマシンなので、動作品が簡単に手に入るとは思えなかった。

 

いろいろと手を尽くしてようやく手に入れたHC-88。

手に入れてからもいろんな事情で触る事が出来ず、もーガマンならんとV20エミュレータを中断してまで触りだした。マシンのメンテナンスから始まり開発環境を整え…という流れは、このブログでリアルタイムに書いてきたので、なんとなく分かってもらえるはずだ。

そんな道のりだったので感慨深い。じーんときちゃうw

 

タロットカードを表示してみる!

さあ!6301を直接制御してグラフィックを表示してみるよ!

まずは…表示すべきグラフィックデータのフォーマットすら分かっていないので、メインCPUからスレーブCPU(6301ね)を介してVRAMへデータを書き出すテストをしてみた。

 f:id:PocketGriffon:20201027032344j:plain

なるほど、どうやらグラフィックフォーマットはHC-40と同じらしい。データをそのままコピーしてもってきたら表示された。

それにしても………なんでこんなに表示が遅いの…。あまりの遅さにTwitterでご報告。

 

 Z80と6301のやりとりに異常に時間が掛かってしまうっぽい。

私のプログラムの作り方の問題なのかなぁ…分からぬ(T-T)

 

でもこの見せ方は、良心的な読者を詐いているところがある。

実はHC-80にはユーザー定義文字が存在する。PCGと言った方が伝わりやすいかも知れない。VRAMに32キャラクタ分の領域(256バイト)確保されているので、ちゃんとした手順で定義してやれば、BASICのPRINT文の速度で表示させる事が可能なんだと思われる。

おそらく今回作った↑プログラムよりも高速なはずだ。

 

しかし今回やってみたい「事」は伝わったと思う。

6301上で直接プログラムを動かして描画させてみるよ!!

 

いろいろと準備が必要!

まず前回作った画面反転プログラムを可能な限り利用する事とする。

6301CPU側のプログラムコードの先頭アドレスは$8000とした。この領域は、本来ならばユーザー定義文字(PCG)のデータ格納場所だ。今回は使わないので利用させてもらう。

 

次に使用しても良いゼロページについても、前回からもう少しだけ調査を進めてみた。利用して問題なさそうな領域を、もう少しだけ探しておきたいのだ。

6301側のプログラムを追い掛けてみたところ、どうやら$90〜$97までの8バイト付近は利用してもよさそうだと分かった。ここはカセットドライブ関連のワークとなっているようだが、ユーザープログラム実行中には使わない。この8バイト+$D0〜$D3の 4バイト、合計12バイトを確保した。

よし、これで戦える!(^^;

 

れっつ6301プログラミング♪

さて…じっくりと腰を据えて6301でのプログラミングを楽しんでみよう!

アセンブラアセンブラは作ったけれども、プログラムを本格的に作るのは今回が初めて。

そんな初心者が何にハマるのかを解説していってみたいw

 

メモリコピーはどうやる?

まず最初に疑問に思ったのが、インデックスレジスタが1つしかCPUで、メモリコピーはどうやるのが良いんだろう…って事だったw

2つのメモリを扱うワケなので、普通に考えたらインデックスレジスタは2つ必要。でも1つしかない…これは…ベタな方法でなんとかするしかない?

f:id:PocketGriffon:20201027093748j:plain

$D0(ワークエリア)に転送先アドレス、Xレジスタに転送元アドレス、Bレジスタに転送バイト数を入れてコールする。ニーモニックが見慣れないと思うので、同じような事をするコードをZ80でも書いてみた。

一部、Z80には本来無い命令を書いてるのでご注意(←の行)

f:id:PocketGriffon:20201027093952j:plain

00D0hに転送先アドレス、HLレジスタに転送元アドレス、Bレジスタに転送バイト数を入れてコールする感じで書いてみた。incは実際にはないので雰囲気として読み取って欲しい。

Z80の場合は転送数によってはLDIR使った方がプログラム短くなるね。

 

うーむ、6301では1バイト転送するのにこの命令数か…これは慣れていくしかないんだろうな。慣れないニーモニックとも戦いながらパズルを組み合わせていく。

 

やっぱり逆アセンブラアセンブラを先に作って正解だったかも!全く知らないというニーモニックがないのは強み(^^) みんな見た覚えがあるし機能だって理解出来てる。パズルのピースが頭に入ってる状態だ。

 

今回に限って言えばタロットのグラフィックスデータは横32ドット、つまり4バイトのデータが転送出来れば良い。

4バイト転送に機能を限定して作ったのがこちら↓

f:id:PocketGriffon:20201027101843j:plain

↑これはHC-88の実機(6301CPU)で動いてるプログラムをそのまま掲載してる。やっていることは、グラフィックデータ4バイトをVRAMへ転送し、それぞれのアドレスを更新しているだけだ。

途中abxという分かりづらい命令が出てくるが、これはX=X+Bをしてくれる便利な命令。Bレジスタを符号拡張してくれるかどうかまで分かってない(^^;

 

これをZ80で書いてみるとこうなる↓

f:id:PocketGriffon:20201027104024j:plain

……うぬぬ…Z80がものすごーく優秀なんじゃないかと思えてきた(^-^;

 

座標計算はどうやる?

 なんとなく6301の優位性が示せないままテキストが進んでいるが(意図的ではないw)、ここいらで一発、ノーマルZ80では出来ない芸当をお見せしたい。

 

VRAMのアドレス計算において、普通に考えたら乗算が必要となってくる。

HC-88のグラフィックVRAMは横480ドット、8ドットが1バイトなので60バイト構成となっている。VRAMのアドレス計算は、Y*60+Xだ。

本来Xはそのまま足しちゃイケナイw なぜならば、ついさっきも書いた通り8ドット1バイトなので、あらかじめXを8で割ってやらないといけない。ここでは話が面倒なので、そのまま加算する事にする(次回修正する予定)。

 

この一見すると面倒そうな計算、さっきのメモリ転送でも苦戦してた6301でどういうプログラムになるのか…。

f:id:PocketGriffon:20201027110134j:plain

おお!意外に短い!

これは乗算命令(mul)が6301にあるおかげ。mulするとAレジスタ*Bレジスタをして、結果をDレジスタ(AB合体)に格納してくれる。

あと特徴的な命令と言えばxgdx。もーね、ニーモニックが暗記出来ない(^^; 多分、「ExchanGe of D and X registers」なんだと思うけど確信はないw Z80風に言えば「EX DE,HL」だ。あとはさっきも出てきたabxがあるくらい。

 

ここまで作るのに何度となく作り直してる。動作確認は簡単ではない。なにせメインCPUの向こう側にいるCPUなので、ハングアップしたとしてもソースをじっくり見る以外に修正する方法がない。そもそもプログラムが動いてるかどうかの確証すらないのだ。手探り感がものすごい!w これが楽しくてレトロやってると言っても過言では無い(^0^)

 

同じ事をZ80で書くとこんな感じ?

即席で書いてるし動作確認もしていないので、雰囲気でお願いね(^^;

f:id:PocketGriffon:20201027110805j:plain

やっぱり乗算命令は強かった!

Z80でもKC80やR800、HD64180のように乗算命令を持つタイプを使うと、この優位性は一気に逆転する。いつかMSX TurboR(R800)でも書いてみたい。

 

私にしては珍しく、描画プログラム全体を載せてみる気になった。

覚えたての6301で書いたプログラムなので、間違いなく改善点はあるんだろうけれども、まぁ今日の時点ではこれが持ちうるチカラの全てって事で!

f:id:PocketGriffon:20201027111343j:plain

 

 Twitterでご報告しつつ動画を載せてみた。ほぼ一瞬でタロット10枚が描画されているのが分かると思う。本来の6301ってこんな速いんだ!って素直に驚いたw

 

6301アセンブラの使い心地は?

今回のプログラム開発に、先日作った6301アセンブラを実際に用いている。これを作ったおかげですんなりとプログラム開発が……進むと思ったでしょ?(T_T)

実際のところは悪戦苦闘ばかり!

 

まずアセンブラがちゃんとしたコードを出力しているのか信頼性が足りないw 間違ったバイナリを出力している可能性があると常に疑っちゃうのだ!出てきたバイナリとソースコードを1行ずつ照らし合わせていく、逆アセンブラに掛けてみる等、地道な作業が必要だ。

 

開発中に気が付いたんだけど、なんとmul命令がすっぽり抜けていたw アセンブラのプログラム的にはデータを1行追加すれば終わる話なんだけど、他にも抜けているものがないか全チェックするハメになった。そしたら全部で4命令の実装し忘れ。あやうく新しいCPUを創造してしまうところだったw

 

あと使っていて「あ、これは無いとアカン」と思ったのは、ロケーションカウンタ。「今のアドレスを示す」というヤツだ。アセンブラによって「$」だったり「*」だったりまちまち。

    jr nz,$+3

    xor a

    ld b,#nn ←ここにジャンプする

みたいな感じで使う。ジャンプさせたいんだけどラベルを作るほどじゃないんだよな…って時に使ったりする。人によって使用頻度が違う気がするけど、私は相当な頻度で使っちゃう人。これは出力されるプログラムバイナリのサイズを暗記しているから手軽に使えるんだと思う。

 

これは改良せねば…と思うんだけど、記号を何にするかで字句解析部分を変更しないとならんのでちょっとだけ厄介。思わぬバグを引き起こしそう…いっその事、絶対に使わないような記号にしちゃおうかな(をぃ まぁこれも自分しか使わないと思ってるツールだから出来るワザだけどw

 

このあとは?

このあとももう少しだけHC-88使おうと思う。

ドット単位にグラフィックを動かしてみたいというのが1つ。

メインCPUとの通信が異常に遅い原因を調べておきたいというのが1つ。

前者は今の流れでプログラムを追加していけば良い。後者についてはROMのプログラムを変更するのは不可能なので、独自でプログラムを作る際の新プロトコルとして実装するしかないんだろうなーって感じ。

今の遅さだとメインでゲーム動かしてサブで描画ってのが成り立たないくらい遅いw せめてそのくらいまでは使いこなしたいなと思う。

こんな令和の時代にHC-80を使いこなすも何もないんだけどねw

自己満足の世界です!!!(言い切ったw

 

ではまた次回!(^-^)ノ