HC-20を使う その6

f:id:PocketGriffon:20210811090724j:plain

せっかくなので何かHC-20(HX-20)で作ってみたい!

そう思ってゲームを作り始めたのだが……やっぱり途中で飽きてしまった(^^;;

 

私は趣味で開発したゲームというのが数える程度しかない。最後までちゃんと作り終えたのは2本のみ。あとは全部中途半端かも知れないw 移植もタイトルが出てゲームが始まればそこで終了、最後まで通して遊んでみるとかしない。

興味の対象がゲーム開発にない事は明らかだ!(^-^)

 

上の発言とは矛盾するが(察して!)、今までゲームはたくさん作ってきているので、もはや技術的に難しいと感じる事がないから…なのかも知れない。先が見えてしまった行程ほど気合が入らない事はない(T-T)

 

というわけで、今回は総集編という感じでHC-20(HX-20)でプログラムする上でのあれこれを書いてみたいと思う。

 

 

全体的な構成

全体としては「仮想画面を更新」「画面全体を書き直す」というのを繰り返しているだけだ。

画面は部分的に書き換えるなどの最適化もしてなく、全く更新されていないスコアなども毎回律儀に全部更新されている。ようするに最適化する前の段階で終わってるって事だ。

 

垂直同期信号での速度調整…なんてしていないので、倍速で動くHC-20ならば倍速で動いちゃう。ゲームとしての基本構成が完全に破綻している(^^;;

 

仮想ビットマップ情報(仮想VRAM)

内部で大きめな仮想ビットマップ情報(以下仮想VRAM)を保持している。画面サイズは120x32ドットだが、仮想VRAM内部では128x32の構成となっている(全部で512バイト)。

これは横方向を2のn乗にしておく事で計算をラクする狙いがあったが、乗算命令(Mul)を持つ6301では効果が感じられなかった。

 

仮想VRAMは横方向に128x8ドット分が連続している。HC-20(HX-20)のVRAM構成と異なっているが、これは専用の転送ルーチン(前回のブログで説明したもの)が差を吸収している。そのため、仮想VRAM中のアドレス計算および描画そのものが高速化出来ている。

 

縦のドット単位スクロール

多分、これがこのプログラムで一番の技術的なところかも知れない。

 

仮想VRAMは縦方向に8ドットが1バイトとなっていて、アドレスを+1すると右の8ドットへ移動していく。この仮想VRAMの構成では(どちらかと言えば)横スクロールの方が得意だ。

 

縦方向にドット単位にスクロールするということは、縦方向の連なる32ドット(つまり4バイト分の情報)を上方向にシフトする必要がある。

f:id:PocketGriffon:20210811095023j:plain

いきなりプログラムコードを載せてしまうが、これで32ドットを上方向にスクロールさせている。大きく3つのブロックに分かれていて、上ブロックが「画面下側16ドットの上スクロール」、中央が参照する仮想VRAMのアドレス更新、下ブロックが「画面上側16ドットの上スクロール」だ。

 

下16ドットは「lsrd」で16ドット分を一気にシフトしている。この命令でMSBには0が入り、LSBにあったビットはCarryフラグに移動する。

 

そしてこれ以降はCarryフラグが更新されない命令のみで構成されている。中央にある「deca」は仮想VRAMのアドレスを16ドット上に更新している(意味が伝わるかな?)。

 

上16ドットも同じように「lsrd」で一気にシフトしたかったのだが、この命令はCarryフラグを含めたシフトをしてくれない。しかたなく「rora」「rorb」で8ビット単位にローテイトしている。「rord」という命令があったら楽だったんだけど、どうやら存在しないようだ(T-T)

 

この一連の操作を、ゲーム画面の横幅分してやれば、ゲームフィールド全体が1ドット上にスクロールする。速度的に大丈夫だろうか?と思ったが、動画を見てもらったら分かる通り、まぁ許せる範囲の速度となっている。全体の速度に直結する部分なので、もっと良い方法があったらぜひ採用したいところなのだが…。

 

一番下にドットを埋める方法は、仮想VRAMに$80をORしていけば良い。

f:id:PocketGriffon:20210811102418j:plain

またしてもプログラムコードを載せてしまうが、6301には「oim」という命令が存在する。これはレジスタを介さずにメモリとOR演算をしてくれる便利な命令だ。「Or Immediate Memory」の略なんだと思うけど、私は親近感を持って「おいむ」と呼んでいるw

 

6301のインデックスアドレッシングでのオペランド指定が少しややこしい。

Z80や6809では符号付き8ビットの値として扱われるのに対して、6301では符号なし8ビットとして扱われる。他のCPUに慣れた人ほどハマる問題かと思う(案の定ハマったw)

 

キー入力

実はこの部分のみ、メモリ中にあるワークエリアを参照している。HC-20とHX-20とで互換性は保てるのか…と心配になったが、解析してみた結果(たまたま?)同じだった。

f:id:PocketGriffon:20210811103122j:plain

RAMの$0145から上記のキー情報が入っている。資料などを見ると「ROM内ルーチンのKEYSCN($FF6A)を呼び出すと、このメモリにセットされる」と書いてあるのが多いけど、実際には割り込み処理などでここにデータが格納されているようなので、いきなり読んでも大丈夫。

 

あと実装するべきは…

あとはプレイヤーと壁の衝突判定(仮想VRAMのドット情報を見れば良い)、スコア加算&表示、そしてゲームのシーケンスを組み立てたら遊べるようになるかな? もう少し頑張ってプレイヤーの爆発アニメ、サウンドなどを入れたら完璧かも?

 

そこまでの気力&時間がないので、今回はここまで!とする!(一方的w

 

勝手なHC-20総評

正直、HC-20に取り組む前までは「614kHzで動いてる6301CPUでどこまで出来るんだろう…」という不安が大きかった。大好きなEPSON機といっても、HC-40/HC-80とは世代が違うため、内部構造も大きく違うと想像していた。

 

実際に使ってみるとHC-20は本当に良く出来た構造だと感じた。特に感心したのは、この時代において互換性の事を考慮した作りになっていた事だ。実際のROM内ルーチンのアドレスがずれても平気なように、(オーバーヘッドを覚悟した上で)固定の場所を用意したのは素晴らしい。おかげでHX-20との互換性も保たれている。

 

HC-80の時に取り組んだ6301とは一味違った感覚でコードを書けた。HC-80の時は「メインCPUの先にあるモノ」だったので、小さな穴から覗き見をしながら機嫌を損ねないように扱うイメージだった。だけどHC-20はメインCPUが6301だったので、もはややりたい放題だw

書いたコードがダイレクトな動きとして見られる安心感はすさまじい。

まぁこれはHC-80で苦労していたから感じた感想かも知れないw

 

やり残し

やり残した事が1つある。あるけど実際にやるかどうかは分からない(どっち

HC-20はサブCPUにも6301が積まれている。感覚的には6809を2つ積んでいるFM-7などと良く似ている。FM-7などのように脚光を浴びていないのがちょっと残念だ。

 

メインCPUからサブCPUへはSNSCOM($FF19)というROM内ルーチンを介してやりとりをしているのだが、このコマンドが100以上にも達する。その中に「サブCPUのメモリへデータを読み書きする」「サブCPUの実行を指定したアドレスに移す」などの楽しそうなコマンドがあるのだ!

 

大した意味もなく「サブCPUにプログラムを送り込んで実行する」をしてみたいw 誰得な実験にはなるんだろうけれど、HC-20での残された興味はココに集結してるかも!

いつか気が向いた時にチャレンジしてみたい(^-^)

 

補足

今回に限り…だけど、中途半端なゲームでもいいからソースを見てみたいという方がいたらお送りしたいと思う。全てのファイルではなく、あくまでもゲーム本体のみ限定。

しかも特殊な環境でしかアセンブル出来ないので、注意して欲しい。

アセンブラが特殊(自作してるので他のアセンブラでは通らない可能性が高い)

・環境として完結していないので、動くバイナリを得るために努力が必要

・HC-20へRS-232C経由で送り込む環境が必要

・多分増設メモリは必要ないと思うけどテストはしていない

・HX-20でのみテスト済み、HC-20でも動くとは思うけど実験していない

・6301初心者のコードであり、全く参考にはならない

 

要するに手元でアセンブルするためには、相応の知識と手間と根性が必要という事だ。

こんな中途半端なものでもいいよ…という稀有な方は、TwitterのDMでご連絡くださいw

2021年8月中のみ対応します(^^)

 

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