見出し画像

MSX マシン語でスプライトを動かす その2

前回記事ではジョイスティック(厳密にはカーソルキー)を使ってスプライトを動かすコードについて説明しました。今回記事では、同じソースコードを使って「ワークテーブル」という考え方について説明します。
https://github.com/sailorman-msx/games/tree/main/src/sample007


ワークテーブル

テーブルとは表の意味です。ワークテーブルは作業用の表という意味と思ってください。前回のソースコードではSPRDISTPTN_TBL(data_sprite.asm)という仮想表を定義しています。(厳密にはWK_PLAYERSPRATTRもワークテーブルです)
SPRDISTPTN_TBLはジョイスティックの向きにあわせて表示するスプライトのパターン番号を表として管理しています。

SPRDISTPTN_TBLのイメージ

MovePlayerサブルーチン(sprite.asm)では以下の箇所でこの表を使っています。

    ;--------------------------------------------
    ; スプライトの移動量TBLのアドレスを取得して
    ; HLレジスタに格納する
    ;--------------------------------------------
    ld b, a ; Bレジスタにジョイスティックの方向の値を退避

MovePlayerSectionUp:

    ;--------------------------------------------
    ; スプライトの方向によってHLレジスタの値(ポインタ)
    ; を変更する
    ;--------------------------------------------

    cp 1 ; ジョイスティックの方向は上か?
    jr nz, MovePlayerSectionRight

    ld ix, SPRDISTPTN_TBL

    ; 方向は上
    ; 移動処理にジャンプ
    jr MovePlayerMoveProc

MovePlayerSectionRight:

    cp 3 ; ジョイスティックの方向は右か?
    jr nz, MovePlayerSectionDown

    ; 方向は右
    ld ix, SPRDISTPTN_TBL + 1

    ; 移動処理にジャンプ
    jr MovePlayerMoveProc

MovePlayerSectionDown:

    cp 5 ; ジョイスティックの方向は下か?
    jr nz, MovePlayerSectionLeft

    ; 方向は下
    ld ix, SPRDISTPTN_TBL + 2

    ; 移動処理にジャンプ
    jr MovePlayerMoveProc

MovePlayerSectionLeft:

    cp 7 ; ジョイスティックの方向は左か?
    jr nz, MovePlayerEnd ; 斜め方向は無視する

    ; 方向は左
    ld ix, SPRDISTPTN_TBL + 3

LD IX, … の箇所です。IXレジスタにはジョイスティックの向きにあわせたパターン番号を格納しているアドレスがセットされる仕組みなっていて、CreateWorkSpriteAttr(sprite.asm)でこのIXレジスタを使ってパターン番号をセットしています。

CreateWorkSpriteAttr:

    ;--------------------------------------------
    ; ワーク用スプライトアトリビュートテーブル
    ; を作成する
    ;--------------------------------------------
    ld iy, WK_PLAYERSPRATTR

    ; スプライト1枚目

    ld a, (WK_PLAYERPOSY) ; Y座標

    ; Y座標を8倍する
    ld hl, 0
    ld e, a
    ld h, 8
    call CalcMulti
    ld (iy+0), l ; Lレジスタに座標値が入っている

    ld a, (WK_PLAYERPOSX) ; X座標

    ; X座標を8倍する
    ld hl, 0
    ld e, a
    ld h, 8
    call CalcMulti
    ld (iy+1), l ; Lレジスタに座標値が入っている

    ld a, (ix)   ; スプライトパターン番号
    ld (iy+2), a

    ld a, (WK_PLAYERSPRCLR1) ; カラー
    ld (iy+3), a

    ; スプライト2枚目
 
(以下、略)

LD A, (IX)
LD (IY+2), A
↑この箇所で、AレジスタにIXレジスタの指し示すアドレスの中の値がセットされ、さらにIYレジスタ+2のアドレスの中にAレジスタの値をセットしています。(IYレジスタはWK_PLAYERSPRATTRの先頭アドレスがセットされている)
理解できますか?
実際、このワークテーブルがなくてもプログラムが書けるのですが次回のサンプル以降はもっとワークテーブルが出てくるので「ワークテーブル」という考え方を説明しました。

IXレジスタ(IYレジスタ)とワークテーブル

今回のワークテーブルは4つなので変数を4個作ればまかなえます。でも、仮にたとえば50個とか100個とかあったりする変数だとどうでしょう?50個変数を定義する?そんな面倒なことはしません。そういう時にワークテーブルという考え方を使います。他の言語で例えたら配列(Dimension,Array)とかそういうやつです。

IXレジスタやIYレジスタは(IX+3)などと書くと、先頭から+3バイト先のアドレスを指します。こういう役割を持つインデックスレジスタのことをポインタと呼んだりします。
上記ワークテーブルのイメージ図では2バイトずつ並んでいます。
例えばこのアドレスの中にまた違うアドレスを入れたりすると表を何個も数珠繋ぎの様につなげることができます。

ポインタのポインタで表を数珠つなぎに定義できるようになる

上記図で以下のようにコーディングするとIYレジスタはC_ADDRを指すことになります。理解できますか?

LD IX, WK_HENSU_TBL + 4  ; IXレジスタにWK_HENSU_TBL+4のアドレスをセット
LD IY, (IX)              ; IYレジスタにIXレジスタ(ポインタ)が指すアドレスの内容をセット

IYレジスタもポインタですから、このような場合ではIXレジスタことを「ポインタのポインタ」と呼んだりします。

どのようなワークテーブルを作るか、どのようにポインタを制御するコードを書くか。がマシン語プログラミングではとても重要になります。

次回は当たり判定です

今回はここまで。

次回はVRAMを使った当たり判定について説明します。
当たり判定が出来ればいわゆる「追いかけっこ」「鬼ごっこ」ゲームは出来るようになります。だんだんゲームプログラミングっぽくなってきました。

次回ではワークテーブルをゴリゴリ使うので今回の記事を理解しておいてくださいね。

では、また!

いいなと思ったら応援しよう!

MSXのZ80で何か作る
セーラー服が似合うおじさんです。猫好き、酒好き、ガジェット好き、楽しいことならなんでも好き。そんな「好き」をつらつらと書き留めていきます。