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


戻る