MZ-800にS-OS"SWORD"を移植する
ソフトなければただのMZ
97年4月にようやっと入手したMZ-800ですが、ソフトがただの1本もついていませんでした。ないわけではないようですが、先方はコピーする方法がよくわからないと言いました。丁寧に教えたつもりですが、教えたツールが見つからなかったか、あるいは英語が下手だったか、さらに1年経っても送ってくる気配はありません。
どうせ送られてくるソフトもドイツ語だろうし、ちょっと工夫すれば日本版のBASICだって使えるということであっさりあきらめることにしました。でもP-CP/Mくらいは欲しかったな…。で、その代わりになるものと言えばS-OS"SWORD"。そう、私にはS-OSというものがあったじゃないですか。せっかくFDDもあることだし、何にも使えないのではあまりに悲しいですからね…。
剣士は構えた剣で言葉を交わす
S-OSとは何そや?という人にはこちらを見ておいていただくとして、MZ-700/1500のS-OSをそのまま起動したらどうなるのかを説明する必要があるでしょう。
MZ-700/1500のS-OSは巷で言うところのBIOSを0番地からのROMモニタに頼っています。これらのモニタは1Z-009Aまたは1Z-009Bという型番になっていますが、中身は同じ物といえます。S-OS起動時にはこのROMモニタをRAMに転送してテープのボーレートを変更できるようにしています。このところがMZ-800ではどうかというと、モニタの型番は1Z-013B、カナモードがないせいか内部構造も1Z-009A/Bと違っていて、テープルーチンの場所が変わっていたりします。ルーチンの呼び出し方法はメーカー推奨のものなのでテープのアクセスそのものはできるのですが、ボーレートに関しては全く違うところにパッチをあててある状態のようです。実はまだ詳しく解析してないのですが、この異常なパッチのせいか画面関係も2行ずつスクロールしてみたり、小文字のディスプレイコードが違うためにその出力も異常となっています。
そこでとりあえずの対策として、MZ-700から1Z-009Aをコピーし、MZ-1500からCGROMをコピーしてきて、これを一旦立ち上がったS-OS上でモニタとCGをRAMとPCGに転送することにしました。700モードのMZ-800は新設ポートをいじらない限り700と完全コンパチですから、モニタとCGさえ日本語仕様にすれば全く国内仕様と同じに使えるわけです。ですが、これをもって「S-OSを移植した」とは言いたくありません。なぜならMZ-800にはK/Cの系統として初めて80桁×25行のキャラクタ表示、640×200ドットのグラフィックが標準装備されているのです。これをS-OSで使用しない手はないでしょう。
手がかりはサービスマニュアル
せめてもの救いとして、同梱されていたのがサービスマニュアル。いわゆるサービスマンが修理のときに参照するマニュアルというイメージがありましたが、確かに各部品と装着位置の図解なんかも載ってありましたが、I/Oポートの内容や動作の説明、メモリマップなどかつて「活用研究」とかいう題名の本にあるようなことが主に記述されてありました。これならプログラムを組むことができそうです。
800モードの時、画面は全てグラフィックとなります。つまりはビットマップディスプレイですね。横640ドットと320ドットを選択できて、解像度によって表現できる色の数が変わります。MZ-2000など、たいていの機種ではRGB各プレーンに対応するグラフィックページは別々にメモリにマッピングされましたが、MZ-800では1プレーン分しかマッピングされません。色の指定はどうするのかというと、これから描きたい色をレジスタにセットして、グラフィックにアクセスするのです。書き込むデータについて、結果をORとするのかANDとするのか、あるいはPSETかとかを色と同時に指定します。平たい話が「複数プレーンの同時アクセス」です。しかも同時アクセスしかできません。この色の指定と描画の指定を工夫すれば、各プレーンに対して独立的にアクセスできると考えられます。
画面がグラフィックということでスクロール速度が遅くなりそうな気がしますが、なんとハードウェアスクロール機能があります。といっても表示開始位置(オフセット)を指定する簡単なもので、上から消えだ行は下から現れます。従って、そこだけをスクロールの前後で消せばOK。何ドットずつスクロールするかも自由なので、スムーススクロールも可能です。
あとはパレット関係をおさえておけば、プログラムは組めそうです。
おお、サービスマニュアルにバグが
というわけで、まずは習作として「全てのキャラクタが色を変えながらスムーススクロールする」というプログラムを作ってみました。ここにソースリストを載せておきましょう。
;
; MZ-800 DISPLAY TEST PROGRAM
; 1988.4.12 Oh!Ishi @ Nibbles lab.
;
ORG 7000H
;
INIT:
LD A,06H ;DMD
OUT (0CEH),A ;640*200,4 colors
LD A,8FH ;WF
OUT (0CCH),A ;REPLACE,Frame A
;Light white
XOR A ;BCOL
LD BC,06CFH ;black
OUT (C),A
OUT (0F0H),A ;PLT0=black
LD A,19H
OUT (0F0H),A ;PLT1=light blue
LD A,2AH
OUT (0F0H),A ;PLT2=light red
LD A,3CH
OUT (0F0H),A ;PLT3=light green
IN A,(0E0H) ;CGROM,VRAM appier
XOR A
LD BC,04CFH
OUT (C),A ;SSA=0
LD A,7DH
INC B
OUT (C),A ;SEA=7DH
LD B,3
OUT (C),A ;SW=7DH
XOR A
DEC B
OUT (C),A ;SOF2=0
DEC B
OUT (C),A ;SOF1=0
;
XOR A ;clear screen
LD (8000H),A
LD HL,8000H
LD DE,8001H
LD BC,4000H
LDIR
;
START:
LD SP,7F00H
LD C,0
START1:
LD HL,1000H ;CGROM addr.
LD DE,0000H ;X=0,Y=0
;
CHR1:
PUSH DE
CALL XYADR ;get VRAM addr.
LD B,8
LIN1:
LD A,(HL)
LD (DE),A
;
PUSH HL ;DE=DE+80
LD HL,80
ADD HL,DE
EX DE,HL
POP HL
;
INC HL
DJNZ LIN1
;
LD A,20H
CP H
JR NZ,DEMO1
LD HL,1000H
CALL COL
DEMO1:
POP DE
INC D ;X=X+1
LD A,80
CP D
JR NZ,CHR1
LD D,0
INC E ;Y=Y+1
LD A,25
CP E
JR NZ,CHR1
DEC E ;Y=24
CALL SCROL
JR CHR1
;
; CONVERT X,Y -> VRAM ADDR
; D <- X , E <- Y
; ADDR -> DE
XYADR:
PUSH HL
LD A,(SOF)
ADD A,E
CP 24
JR NC,XYADR1
SUB 25
XYADR1:
LD A,E
SLA E
PUSH DE
LD D,0
LD HL,YPOS
ADD HL,DE
LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL
POP DE
LD E,D
LD D,80H
ADD HL,DE
EX DE,HL
POP HL
RET
;
SCROL:
PUSH DE
PUSH HL
LD DE,0000H ;X=0,Y=0
CALL XYADR
XOR A
LD (DE),A
PUSH DE
POP HL
INC DE
LD BC,639
LDIR
;
LD A,(SOF)
SLA A
LD E,A
LD D,0
LD HL,SPOS
ADD HL,DE
LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL
;
LD DE,5
LD B,8
JR SCROL1
SCROL4:
PUSH BC
LD BC,1000
SCROL3:
DEC BC
LD A,B
OR C
JR NZ,SCROL3
POP BC
SCROL1:
ADD HL,DE
PUSH BC
LD A,L
LD BC,01CFH
OUT (C),A
LD A,H
INC B
OUT (C),A
POP BC
DJNZ SCROL4
;
SCROL5:
LD A,(SOF)
INC A
CP 25
JR NZ,SCROL2
XOR A
SCROL2:
LD (SOF),A
POP HL
POP DE
RET
;
COL:
LD A,(COLOR)
OUT (0CCH),A
CP 81H
JR NZ,COL1
LD A,84H
COL3:
LD (COLOR),A
RET
COL1:
CP 84H
JR NZ,COL2
INC A ;A=85H
JR COL3
COL2:
LD A,81H
JR COL3
YPOS:
DEFW 0,640,1280,1920,2560,3200,3840,4480
DEFW 5120,5760,6400,7040,7680,8320,8960
DEFW 9600,10240,10880,11520,12160,12800
DEFW 13440,14080,14720,15360
SOF:
DEFB 00H
COLOR:
DEFB 81H
SPOS:
DEFW 0,40,80,120,160,200,240,280,320,360
DEFW 400,440,480,520,560,600,640,680,720
DEFW 760,800,840,880,920,960
サービスマニュアルには640×200モードの時は各GRAMのアドレスが奇数番目と偶数番目で前半と後半のメモリに分かれる(わかりにくい表現だこと)とあったのですが、本当は横320ドットの時と同じように頭からわりふってありました。あとは経験的にわかったことですが、リセット時のパレットの初期化はモニタではされておらず、またハード的にも不定値になるようなので必ず設定しないといけません。なお、リストの最後にある数値のかたまりはY軸とスクロールオフセットのテーブルです。掛け算って専用命令がないとわりと面倒ですから、手っ取り早く作るためにテーブルを用意したというわけです。
今んとこはここまで
このあと1Z-013Bを逆アセンブルして解析する予定です。これにパッチをあてるような格好で作れれば、つまり文字表示ルーチンとか使わないだろうMUSICルーチン(BELLは鳴らさないといけないのでその機能だけは作り替えてでも残すけど)と新しい表示ルーチン等をすげかえることで作れればいいな、と思っています。そのために1Z-009Aのリストが必要なのですが、実は持ってません。ある人に頼んでいるところで、それが来たらおもむろに始めようと思ってます。ちなみに、同じ方法で第2ROMである9Z-504MをMZ-1500の9Z-502Mのリストから解析しています。完全完成品にはなっていませんが、場所が変わっただけで特段違うところはありませんでした。
今のところ、問題なのは仮想VRAMが必要なこと、カナを表示するにはどこかにフォントデータが必要なこと、英文字データを元からあるやつと流用しようと思うとASCIIコードからの変換がやたら面倒になること、漢字まで表示できるとうれしいけど漢字ROMがないことでしょうか。