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がないことでしょうか。