いまさらベーシックマスターの開発環境を作ってみる(8) GAME68を再移植してみる(1)
NTBは一段落したので、GAME68 (GAME-III)を移植してみる。BASIC MASTERには GAME-MB という移植版があるのだけど、自分でもやってみたい。
(資料を無くしてしまったので、GAME-MBの移植者がわからないです。どなたかご存知ありませんか?)
GAME-IIIのソースは月刊アスキーの1978年7月号から10月号に掲載されている。OCRしてもいいのだけど、ソースを公開してくださっている方がいるので、そちらを使うことにする。
今回もゼロページが足りない
MC6800は 0ページ(0000-00FF)にアクセスするときは、ダイレクトモードアドレッシングが使えて、通常よりも1バイト短い命令が使える。速度もその分だけ速い。
GAMEもダイレクトモードを使いまくっていて、0ページの大半($06-$FF)が使われている。これが移植するときに困る。特に問題になるのは変数・特殊変数の領域で、後述するように連続した126バイトが必要である。非常に困る。
GAMEが使っている0ページのうち、第1スタック・第2スタック・入力バッファは他のページの方が良い。ただのデータに貴重な0ページを使うのはもったいない。とは言え、1978年当時はマイコンに使えるメモリは極めて少ないので、0ページも使いまくるしかなかった。
上記スタック等を省くと、残りの作業領域としては$84(132)バイトほどが必要になる。
GAME-MBはどうしていたか
さて、今回移植先のBASIC MASTERは マニュアルの記述によると モニタが00-71番地、BASICが$72-$FFと$400-$9FFを使う。MUSIC無しなら押し込められそうであるが、MUSIC有りだとまだ足りない。
さらにモニタのMUSIC処理(JSR $F00Cで呼べる)は、$C5-$D9あたりも使っているようだ。また、割り込み時やモニタ入力時の一時的なスタックとして $FFを設定している(LDS #$00FF)ので、このあたりも使いにくい。
結局、MUSIC無しで$72-$F?(126バイト+α)、MUSICありだと$72-$C4,$D9-$F? (83バイト、23バイト+α)しか使えない。
GAME-MBはざっと調べた範囲では $40-$73、$74-$F8を使っていて、モニタ領域やMUSICの領域も使ってしまっている。にも関わらず、GAME-MBは [=1 で音が出る。調べてみると音を出す前後で変数領域/MUSICの領域を交換して値が壊れないようにしているようだ。豪快である。
後述するように、変数として連続した126バイトを使うためには$74-$f1を使うしかなく、その他にもワーク領域が必要なので、モニタの利用頻度の低い領域(一時的なワークなど)も使っているようだ。
変数用に連続した領域が必要
GAME-III作者の大西博氏の解説記事によると、0ページの使い方は以下の通りである。
エンサイクロペディア・アスキー Vol.2 P.169
変数A-Zは、どのみちインデックスアドレッシングしかしないので、0ページにある必要は(たぶん)無い。変数のアドレス計算はサブルーチンADRVARが行っていて、下記のコードになっている。
例えば、変数A($41)なら、$3FでANDして$01、それに2を足して2倍するので($6,$7)がAの使うアドレスである。上記の表を見てもそうなってる。
ADRVARの処理で、CLRAのところを適当なページすれば移動できそう………と思って別ページに変数領域を動かしたらGAMEの動作がおかしくなった。なんで?
[code lang="asm"]
ADRVAR CLRA
ANDB #$3F
ADDB #2
ASLB
AV1 STX $70
JMP TSTZR0
[/code]
実は、GAMEでは、記号が特殊変数として利用できる。上の表の & ' * = がそれだ。先ほどのADRVARサブルーチンでは、これらの特殊変数のアドレスも同じ式で計算していた。
例えば、 & ($26) なら、AND #$3Fしても$26、2を足して2倍すると$50。表の通りである。ここに対してダイレクトアドレッシングでアクセスしていたので、その部分も変更しないと動作しない。
結局、$41-$5F,$20-$3F までの連続する$3F個(63個)の2バイト変数領域が必要で、これだけで126バイトを使ってしまう。これをGAME-MBのように全部0ページに残すかどうかの判断が難しいが、今回は全部別ページにしてみた。特殊変数だけ0ページに残すのが良いのかもしれないが、後で考えよう。
メモリ節約コードの罠
動作が少々遅くなってもいいと考えて変数・特殊変数を外に出したら、10進表示サブルーチンがおかしくなった。コードは以下の通り。
よくある10進表示サブルーチンで、表示したい数値を10000,1000,100,10,1で割って、商を1桁ずつ表示する。一見問題なさそうだが、よく見ると終了判定が不思議なコードになっている。
終了判定は TST 1,X で行っているので、 FDB 1 の次に FDB 0 が欲しいところだが、それが無い。なにこれ?
[code lang="asm"]
BYNDEC LDX #$83
STX $6C
LDX #CTABLE
BDL STX $6E
(中略)
LDX $6E
PULA
INX
INX
TST 1,X
BNE BDL
(中略)
CTABLE FDB 10000
FDB 1000
FDB 100
FDB 10
FDB 1
*
*** POSITIVE DIVISION ***
*
DIVPOS CLR $66
[/code]
CLR命令にはダイレクトアドレッシングがなく、エクステンデッドアドレシングを使っているのがトリックの答えだ。
そのため、CTABLEの次に存在するCLR命令は7F 00 66となり、2バイト目が0になるのでTST命令で検出できる。
$66を別ページ(例えば$0466)に移すと7F 04 66となり、TSTが成立しない。なんというテクニックだ。
作業途中の画面
ASCII誌のベンチマークは動くようになった。SAVE/LOADもできた。0ページを使わないのでコードサイズはかなり増えた。遅くなってるような気はあまりしない。
続く
ディスカッション
コメント一覧
まだ、コメントがありません