MSXのGRAPHIC1モードを学ぶ
今回はMSXのGRAPHICモードについて説明します。前回記事のさいごにGRAPHIC2モードの説明をすると宣言していましたが、訂正します。GRAPHIC1モードから説明したいと思います。というのもGRAPHICモード1を理解しないとGRAPHIC2モードの理解が難しいと思ったためです。
SCREEN1(GRAPHIC1モード)
MSXにはSCREEN0、SCREEN1、SCREEN2という画面モードがある。というのは当noteの最初のほうで説明しました。おさらいになりますが、以下の図のとおりです。
VRAMアドレス
文字の形(フォント)が定義されているのはパターンジェネレータテーブルというアドレス空間になります。0000とか0200とかって書いてあるところは0000H、0200Hと読みかえてください。パターンジェネレータテーブルは1文字あたり8バイトで構成されています。MSXでは全部で256文字ありますので256x8で2048バイトのパターンジェネレータテーブルがGRAPHIC1モードには用意されています。
パターンネームテーブルは画面に表示されているデータが1対1で割り当てられています。例えば画面の一番左上に表示されている文字は1800Hのアドレスに格納されています。もちろんその値を変更すると画面の文字の表示も変わります。画面全体は横32x縦24なので768バイトです。
パターンネームテーブルと画面との対応表は以下のとおりです。
VRAMアドレスの1800Hのアドレスに30H('0')を書き込むと、縦0、横0の場所に’0’が表示される仕組みになっています。この対応表はGRAPHIC2モードでも同じです。そのため、あとの記事でも使いますので覚えておいてください。
カラーテーブルは文字ごとの色を定義しているアドレスです。GRAPHIC1モードでは8文字ごとに前景色と背景色とを分けることが出来ます。
パターンジェネレータテーブルとカラーテーブルは次のようなイメージになっています。
文字の形を自由に変えれる。
文字の色を自由に変えれる。(ただし8文字単位)
とだけ理解できればまずは大丈夫です。
とりあえずまずはBASICで文字の形と色を変えてみることにします。
スプライトについてはGRAPHIC2の説明以降としたいと思います。
BASICでも文字の形を変えれる
GitHubにsample003.basというファイルを置いてますのでそちらをコピペしてsample.basというファイルを作ってください。
https://github.com/sailorman-msx/games/blob/main/src/sample003.bas
WebMSXでは、Alt+Bを押すとソースコード入力用の画面が開きます。
コピーしたソースコードをこのダイアログ上でペーストしてOKをクリックするとソースコードを一気に入力することができます。(WebMSX便利です)
ソースコードを入力し終わったら、画面上で「run」と入力してエンターを押してください。
パタパタパタ・・と次のような画面が表示されるはずです。
このプログラムはASCIIコードの30Hのコード、画面的には数字の0(ゼロ)の形をブロックの形状に変更して赤色にカラーを変えています。
ソースコード中にVPOKEという命令がいくつか登場していますが、この命令がBASICからVRAMにデータを書き込む命令になっています。
Z80マシン語でも動かしてみる
当noteではBASICを説明するつもりはありません。とりあえずBASICでも簡単に文字の形を変えれるんだー。ということを伝えたかっただけです。でも、動かしてみてわかると思うのですがモッサリ動くんですよね。なのでマシン語の登場というわけなのです。GitHubにsample003.asmというファイルを置いてありますのでそちらをコピーするなりして、手元にsample003.asmというファイル名で保存してください。保存後はいつものとおり、z80asmでアセンブルしてsample003.binを作ります。
https://github.com/sailorman-msx/games/blob/main/src/sample003.asm
アセンブルして動作させると「パッ!」と表示されることがわかると思います。ちなみにsample003.asmでは違う文字(数字の8)も形状と色を変えています。壁に囲まれた青いひとたちもたくさん表示させてみました。これだけでもレトロゲーム感は出てくるものですね。
ソースコードの説明
今回のサンプルソースコードは以下のような構成にサブルーチンを作っています。
CreateCharacterPattern
キャラクタパターンとカラーテーブルを作る処理
PutVRAM256Bytes
画面の上段・中段・下段の3分の1ずつを表示する処理
CalcMulti
掛け算ルーチン(EレジスタとHレジスタの値を掛け算してHLレジスタに格納する)
じっくり読めばなんとなく理解できると思います。
PUSH、POP
今回のサンプルで初めてPUSH、POP命令が登場しました。
push bc
push de
(中略)
pop de
pop bc
マシン語プログラミンではレジスタを頻繁に使います。ものによっては、このレジスタの値をできれば壊さずにサブルーチンから戻ってきてほしい。ということも多々あります。そのような場合にPUSHとPOPを使います。PUSHを使うとレジスタの値を退避してくれます。処理が終わってPOPを使うと退避していたレジスタの状態が復元します。バックアップみたいな感じとおもってください。「とりあえずキープ」みたいな感じです。
ただし、FILO形式(First in Last out)です。最後にPUSHしたレジスタからどんどん最初にPUSHしたレジスタの順でPOPする必要があります。上記ソースコードでもBC、DEの順でPUSHしているのでDE、BCの順でPOPしています。この順序性はとても重要(というか絶対)です。これを間違えるとまず暴走します。
PUSH、POPを入れ子に書いたりするとまず間違いなく暴走します。PUSH、POPもスタックポインタを使います。
慣れないうちは変数用のアドレスを作ってそこにレジスタの値を退避させてからサブルーチンを呼び出して、サブルーチンから戻ってきたら変数の値をレジスタに戻してあげる。といったやりかたのほうが暴走しないので精神的には安心かもしれません。
筆者は出来る限りスタックポインタまわりは避けてコーディングしています。それが正しいスタイルなのかどうかはわかりませんが。。。
また、BIOSのサブルーチンをCALLするとたいてい、なんらかのレジスタが破壊されます。ご注意ください。
その他は特にかわりなく
その他の命令については今回、新しく登場したものはありません。まずはソースコードを読んでみるところから始めてみてください。重要なのは掛け算ルーチンです。これは説明しないと解らないはず・・。2進数での筆算をソースコードにしているような感じです。私もまだわかりやすく説明できそうにありません。またの記事での説明とさせてください(汗)
もちろん不明点等ありましたらコメント等Twitterでもかまいませんので質問していただければ回答します(回答できるものに限る)
今回の記事でMSXのVRAMについて
GRAPHIC1モードでは文字の形や色を変えることができるんだ。
でもいくつか制約あるみたいだ。特に文字色。
GRAPHIC1モードでもゲームっぽい画面はできそうな感じもする。
と理解していただければそれで良いです。
この理解をベースに次回のGRAPHIC2モードの説明に移りたいと思っています。
では、また!