MSX BASICのBSAVE命令はメモリの内容をバイナリーデータで保存する命令、BLOAD命令はバイナリーデータをメモリへ転送する命令ですが、一体どのくらいのメモリ容量が扱えるのか、知らなかったので調べてみました…と思ったらバグかもしれない場面に遭遇しました。
結論
- BLOAD命令・BSAVE命令ともども、メモリの最大容量は65535バイトまで扱えます。
- メインRAMの最大容量である64kB(65536バイト)以上のデータには対応しません。誤動作が発生します。
- そういう動作をするのは仕様でした。
BSAVE形式ファイルの仕様
今一度MSXのBSAVE形式ファイルの仕様を確認します。
オフセット | 容量 | 内訳 |
---|---|---|
+0 | 1 | BSAVE形式の明示(0xFEが必ず入る) |
+1~+2 | 2 | 開始アドレス |
+3~+4 | 2 | 終了アドレス |
+5~+6 | 2 | 実行アドレス |
+7~ | n | 実際のバイナリデータ |
先頭7バイトがいわゆる「BSAVEヘッダ」と呼ばれるヘッダデータ、以後は実際のバイナリデータが連結されます。MSXはZ80 CPUなので、アドレス指定はリトルエンディアン(下位アドレスから先に記述する方式)となります。
例えばメインRAMのC000hからC00Fhまでの16バイトをBSAVE命令で保存する場合、以下の通りになります。
- BASICコマンドは「BSAVE "(ファイル名)",&HC000,&HC00F」
- 保存されるファイルのBSAVEヘッダは「FE 00 C0 0F C0 00 C0」
- 保存されるファイルのデータ容量は 7+16=23バイト
なおBLOAD・BSAVEともにBSAVEコマンドの末尾に「,S」を記述すると、対象がVRAMになります。
- 「BSAVE"(ファイル名),0,256*212-1,S」← SCREEN8の1画面を保存する
- 「BLOAD"(ファイル名),S」← VRAMへバイナリデータを転送する
BSAVE命令のテスト
↓↓↓ 皆さんも今すぐブラウザ上で動作テスト!
MSX BASICで65536バイトと65535バイトのバイナリデータをBSAVE命令で保存する指示に対し、実際に出来上がるファイル容量を比べてみるテスト → https://t.co/DSSho9AtJE
— Takashi Kobayashi (@nf_ban) 2022年6月1日
結果
- 0000~FFFFh(65536バイト)を保存すると、BSAVEヘッダのみ7バイト(FE 00 00 FF FF 00 00)で保存される。これはバグなのか仕様なのか…
- 0000~FFFEh(65535バイト)の保存は、正常に動作する。
- 保存するデータ容量が65536バイト未満であれば、FFFFhの値は保存できる。「FFFFhが保存できない」というわけではない。
つまり、64kBの1バイト少ない65535バイトがBSAVE命令で保存できる最大データ容量となります。
MSXのVRAMのFFFFhだけ1バイトをBSAVE命令でバイナリ保存したときの検証を念のためやってみたら正常だった件。BSAVEヘッダが気持ち悪い! pic.twitter.com/LShfffSIjB
— Takashi Kobayashi (@nf_ban) 2022年8月8日
もしかしてFFFFhが保存できないのでは?と一時期思ったので念のためFFFFhだけを保存するテストを行ったところ、これは正常に動作しました。
BLOAD命令のテスト
Windowsのバイナリエディタを用いてデータ加工し、BSAVEヘッダが付いた65536バイトの偽バイナリデータを作成しました。その際、BSAVEヘッダの終了アドレスがFFFEhでなくFFFFhで終了するよう偽装してあります。
また、BSAVEヘッダの定義内容と実際のバイナリデータの量が違う偽のバイナリデータも作成し、テストしてみました。
結果
- 強引に作成した65536バイトの読み込みは、正常に読み込めない。フリーズはしないが途中で関係の無いデータが勝手に読み込まれる。
- 65535バイトまでのデータ容量であれば、正常に読み込める。
- BSAVEヘッダの定義よりも実際のデータ量が多い場合は、余分なデータは無視される(読み込まれない)。
- BSAVEヘッダの定義よりも実際のデータ量が少ない場合は、関係の無いデータが勝手に追加される(不定値)。
よって、MSX BASICではBLOAD・BSAVE命令で扱える最大データ量は65535バイトでファイナルアンサーのようです。
バグではなく仕様でした
バグではなく仕様ですね。テクハンに書いてあります。おそらくは、BASIC上では終了番地で指定するけど内部的処理にはサイズで扱うために1バイト削られてるのかと。 pic.twitter.com/vzg4nPjTtq
— EmiCharLounge (@EmiCharLounge) 2022年6月1日
アドレスに入る値の有効範囲は0~65534(&HFFFE)である旨は、テクハン(アスキー刊「MSX2 テクニカル・ハンドブック」)に記載されていました。実際にはエラーは出力されず命令は実行されるので、「有効範囲」という言い方になっているのですね。
なぜそうなるのか仮説
この頃はまだ何も分かっていなかった。
実データが無いBSAVEヘッダのみのファイルの読み込みでゴミ(不定なデータ)が追加されるのは、BSAVEヘッダの定義よりも実際のデータ量が少ない場合は何かのデータが勝手に追加される(不定値)条件だったことが、実験で判明する。
テストしてみたら64kB(65536バイト)のファイルは正常に読めないというオチに…
特殊スキルすぎる!!