能書き
MSX実機やMSX0のBASICモードにおいて、ディスクに保存されている32KBのROMイメージファイルをRAMにロードしてリセットし、そのRAM領域をROMカートリッジとして認識させ、ゲームソフトなどを起動するための手順です。
本エントリの内容はあくまで個人的に実験したいからやっているものであり、MSX-DOS環境が使える場合、SofaRunなどすでに同種のソフトは存在しており、そちらを使うほうが32KB以外のサイズのROMイメージにも対応しており、簡単便利かつ確実かと思われますので、あしからずご了承ください。
ROMイメージをRAMにロードしてROMカートリッジとして認識させるには
先日、16KBのROMイメージをロードする手順について記事にしましたが、32KBのROMは、基本的にページ1とページ2を利用しています。 ページ1はBASICモードではBASIC ROMとして割り当たっているため、マシン語実行中にENASLT BIOSでページ1をRAMが割り当たっているスロットに切り替え、そこにROMの内容を書き込んでいました。
しかしながら、ページ2はBASICモードで通常利用されている領域になるため、BASICモードからプログラムを実行する場合には注意が必要です。 まず、ROMイメージをロードするプログラム自体をページ2に置くことはできませんので、HIMEM(マシン語領域の開始番地)をページ3(C000H)以降にした上で、作成するプログラムの格納位置もC000H以降にする必要があります。
Z88DKでBSAVE形式のファイルを作る場合に、格納開始位置(いわゆるアセンブラのORGで指定するアドレス)を変更する場合は、-zorgというオプションを付けてコンパイルします。詳しくは弊ブログ記事をご参考に。
[MSX] Z88DKでBSAVE形式のファイルを作る場合に格納アドレスを変更するには #MSX #Z88DK
https://mobileff.blogspot.com/2023/12/msx-z88dkbsave-msx-z88dk.html
また、FCBやDMAバッファ(ディスクファイルのアクセス状況を管理する領域と、ディスク内容を読み書きするのに使うバッファ領域)を、16KB ROMのロードでは特に何も考えずmalloc()関数でやっていましたが、これだと、ページ2にメモリを確保してしまうようで、うまく動作できない(FCBやDMAの領域がROMイメージで上書きされてしまうから)ため、決め打ちでそれぞれFCBはE000H、DMAはE000H+37と指定します。FCBが36バイトなので、DMAはその直後に指定しています。
MSX/MSX2では、転送が終わったらソフトリセットしてしまえばよいのですが、MSX2+の場合、リセット後のブートシーケンス内でRAMを初期化してしまうため、転送後に、ROMイメージの先頭から3バイト目(4002H)以降に記載の2バイトがINIT(初期処理としてジャンプする先の番地)になっていますので、ROMイメージロード後に、BIOSコールのCALSLTを使ってROMイメージの入っているRAMのINITへインタースロットコールします。
手順
MSXのBIOS(ENASLT)を使うと、メモリ空間上の特定のページを、任意のスロットのページに切り替えることができます。 ただし、ページ0については、BASICモードでは各種BIOSの内容が格納されている領域のため、ENASLTではページ0を別のスロットのものに切り替えることはできません。 32KBのROMカートリッジは、たいていページ1〜2に割り当てられていることが多いので、ページ1〜2にロードします。
手順の概略は次のとおりです。
CLEAR 100,&HC400
のようにCLEAR文を実行して、ページ3にマシン語領域を確保する- マシン語実行後はBASIC関係ないじゃんって思うところですが、これをちゃんとやらないとBLOAD"xxx",Rしたあと普通に暴走します
- 現状のスロット構成を読み込んで、変数に格納しておく
- ページ1にRAMが格納されているスロットを特定する
- BIOSで調べる方法もあると思われますが、この記事では手動で指定させています。
- ENASLTをコールし、ページ1をRAMの格納されているスロットに切り替える
- ページ2はBASICモードでは最初からRAMに割り当たっているので、ENASLTはしなくても大丈夫です。
- ディスクから1024バイト読み込む
- LDIRを使って、読み込んだ内容が格納されているメモリ領域を、ページ1〜2のメモリに転送する
- 次の1024バイトをディスクから読み込み、以下同様に繰り返す
- 全部ロードし終わったら、ROMイメージの先頭から3〜4バイト目に書かれたアドレス(INIT)を読み取る
- INITが0でない場合は、INITのアドレスにインタースロットコールする
- INITが0の場合は、0000H番地にジャンプ(ソフトリセット)
ソースコード
GitHubにアップしていますので、そちらをご覧ください。
https://github.com/MobileFF/msx0_sample/tree/main/ROMLOAD
注意点
MSX2+以降では、ブートシーケンス中に、RAMの内容をクリアする処理が追加されています。そのため、ROMイメージロード後にソフトリセットしてROMイメージを起動させることはできません。 MSXのROMイメージにおいては、先頭から3バイト目(4002H)以降に記載の2バイトがINIT(初期処理としてジャンプする先の番地)になっていますので、ROMイメージロード後にスロット構成を元に戻さずに、直接INITの示す番地にジャンプするか、BIOSコールのCALSLTを使ってROMイメージの入っているRAMのINITへインタースロットコールすれば、MSX2+以降でも起動が可能なようです。
コメント
コメントを投稿