tunozemichanの日記 / tunozemichan's diary

SORD社のコンピューターM68やM68MXの解析についての備忘録です。This blog is a memorandum about the analysis of SORD's computers M68 and M68MX.

FM-7版S-OS SWORDを動かしました。

FM-7版S-OS SWORDを入力、動かしました。このS-OSは、Oh!MZ1987年8月号に掲載されたものです。FM-7のCPUは6809ですので、Z80用のS-OSは動きませんが、Z80カードというオプションがあり、これによりS-OSを動かすことができます。しかし、これにとどまらず、Z80カードを持っていなくてもZ80エミュレータを実装して動かすというバージョンも同時に掲載されました。まずはディスクイメージを以下に置きます(適当に他のソフトも入っています)。

 

FM-7版S-OS SWORD(Z80カード)

SOS_Z80card_work.D77 - Google ドライブ

 

FM-7版S-OS SWORD(エミュレータ)

SOS_EMU_work.D77 - Google ドライブ

 

掲載されたダンプファイルをOCRで読み取って、データ化、BINファイルまでの手順は、以前、PASOPIA7のS-OS SWORDの記事に書いたのとほぼ同じです。eFM7上で作業しました。

FM-7版ではCP/Mでいうところのディレクトリ情報を短いBASICプログラムを使ってメモリ上に作成してから、起動ディスクを作る点が他機種とは異なるところです。ここはOCRではうまくいかなかったので自分で手入力しました。

あとは出来上がった複数のバイナリファイルを、eFM7のDebug機能で各々の番地に読み込ませていき、最後にディスクへの書き込みBASICプログラムを実行して完成です。

 

 

Z80カード未サポートのeFM7でもS-OS SWORDが動いている。

話題のSLANGコンパイラも動く!

 

SORD M23へのCP/M移植メモ その2(ブロッキング/デブロッキング)

 

SORD M23のブロッキング/デブロッキング

以前にもCP/Mブロッキング/デブロッキングについて書きましたが、改めてSORD M23の場合について書くことにします。

ここからブロッキング/デブロッキングコードaxg.asmを入手します。これをその1に書いたTOZ.EXEを使って、Z80コードに変換します。ここではファイル名をaxg.z80とします。

cpm2-plmフォルダのCBIOS.Z80(CBIOS.ASMをZ80コードに変換したもの)をベースにしてaxg.asmの内容を適宜コピーします。 基本的には全てコピーすればよいですが、boot:とwboot:は何も書いていないのに等しいので、CBIOS.Z80と対応を取りながらコピーします。具体例は別記事として書きます。

 

SORD M23のFDCはMB8877A(FD1771)です。このFDCの詳細はネットでも入手できますが、次にあげる2冊を読む方が理解が速いです。1つは、「トランジスタ技術SPECIAL No.11 フロッピ・ディスク・インターフェースの全て」です。これがないとFDCのコードを書くのはかなり困難だと思います。もう1冊は、このブログで何度か触れた「試験に出るX1」です。

CP/Mの移植で最も参照した資料

 

話を戻して、ブロッキング/デブロッキングで最も重要なのは具体的にフロッピーディスクコントローラー(FDC)を叩く部分です。axg.z80では以下のようにRETしかありません。

;*****************************************************
;*                                                   *
;*  WRITEHST performs the physical write to     *
;*  the host disk, READHST reads the physical     *
;*  disk.                         *
;*                                                   *
;*****************************************************
writehst:
    ;hstdsk = host disk #, hsttrk = host track #,
    ;hstsec = host sect #. write "hstsiz" bytes
    ;from hstbuf and return error flag in erflag.
    ;return erflag non-zero if error
        RET
;
readhst:
    ;hstdsk = host disk #, hsttrk = host track #,
    ;hstsec = host sect #. read "hstsiz" bytes
    ;into hstbuf and return error flag in erflag.
        RET
 

SORD M23では、以下のように書きました。writehst:、readhst:ともにほぼ同じ動作です。まず、SEEKして、ホストセクタ番号(CP/Mの論理セクタではない)をセットして、GO_DMA_AND_WRITE0またはGO_DMA_AND_READ0を実行するだけです。セクタ番号に1を足しているのはCP/Mの論理セクタが0オフセットの為です。これはDISKDEFマクロでセクタが1から始まることを指示しても、0から始まります。

writehst:
    ;hstdsk = host disk #, hsttrk = host track #,
    ;hstsec = host sect #. write "hstsiz" bytes
    ;from hstbuf and return error flag in erflag.
    ;return erflag non-zero if error
        LD A,(hsttrk)
        LD E,A ; E is Track No.
        CALL SEEK
        LD A,(hstsec)
        ADD A,01H
        LD C,A ; C is Sector No.
        CALL GO_DMA_AND_WRITE0
        LD (erflag),A
        RET
;
readhst:
    ;hstdsk = host disk #, hsttrk = host track #,
    ;hstsec = host sect #. read "hstsiz" bytes
    ;into hstbuf and return error flag in erflag.
        LD A,(hsttrk)
        LD E,A ; E is Track No.
        CALL SEEK
        LD A,(hstsec)
        ADD A,01H
        LD C,A ; C is Sector No.
        CALL GO_DMA_AND_READ0
        LD (erflag),A
        RET
;

SEEKは以下のように書きました。シークコマンドを発行してエラーチェックをしているだけです。

;
; SEEK subroutine
; E is Track No.
;
SEEK:
    LD A,E ; E is Track No.
    OUT (FDC_DATA_REG),A
    LD A,1CH ; SEEK COMMAND
    CALL FDCOUT
    AND 98H
    RET
 

GO_DMA_AND_WRITE0:及びGO_DMA_AND_READ0:は以下のように書きました。セクタ番号をFDCのセクタレジスタにセットして、DMAコマンドチェーンを設定して、DMAを起動、FDCにライトコマンド(A0H)、またはリードコマンド(80H)をセットして実行させています。

;
; DMA setting & FDD write FOR SIDE 0
; C is Sector No.
;
GO_DMA_AND_WRITE0:
    LD A,C
    OUT (FDC_SECTOR_REG),A
    LD HL,DMA_WRITE_COMMANDS
    CALL DMA_ON
    AND 20H
    LD A,0A0H ; WRITE DATA COMMAND for Side 0
DO_FDC_WR0:
    CALL FDCOUT
    AND 0FCH
    RET
;
; DMA setting & FDD read FOR SIDE 0
; C is Sector No.
;
GO_DMA_AND_READ0:
    LD A,C
    OUT (FDC_SECTOR_REG),A
    LD HL,DMA_COMMANDS
    CALL DMA_ON
    AND 20H
    LD A,80H ; READ DATA COMMAND for Side 0
DO_FDC0:
    CALL FDCOUT
    AND 0FCH
    RET
;
 

DAMA_ON:は、単にDMAコマンドチェーンの格納されている先頭アドレスをセットして、コマンドをDMAに渡していくだけの処理です。コードの通り、コマンドチェーンの先頭にはコマンド数が入っています。SORD M23のDMAはZ80DMAです。これはSHARP X1と同じですので、「試験に出るX1」をご覧下さい。

;
; DMA setting & Go
; HL is Address of DMA Command chain
;       but top value is No. of DMA Command chain
DMA_ON:
    PUSH HL
    PUSH BC
    LD B,(HL)
    INC HL
    LD C,DMA_ADDRESS
    OTIR
    POP BC
    POP HL
    RET
 

今回のSORD M23への移植ではコマンドチェーンは以下のように書きました。個々のコマンドは「試験に出るX1」に細かく出ています。

; DMA COMMAND CHAIN
;
DMA_COMMANDS:
    DB 15H,0C3H,0C3H,0C3H,0C3H,03CH,0C3H
    DB 0BBH,01H,9BFH
    DB 6DH
    DB 0C3H,0FFH,00H,02CH,010H,08DH
    DB 0D7H,0EAH ; this address is hstbuf address !!!!
    DB 8AH
    DB 0CFH,87H
;
;
DMA_WRITE_COMMANDS:
    DB 16H,0C3H,0C3H,0C3H,0C3H,03CH,0C3H
    DB 83H ; STOP DMA
    DB 79H ; B->A
    DB 0D7H,0EAH  ; this address is hstbuf address !!!
    DB 00H,0FFH ; 256yte transfer
    DB 14H,28H,8DH
    DB 0C3H,00H ; FDC data register
    DB 8AH
    DB 0CFH,05H
    DB 0CFH,87H
 

最後に、FDCコマンドアウトコードです。FDCコマンドレジスタにコマンドを入れて、BUSYがクリアされるまで待ちます。

;
; FDC COMMAND OUT subroutine
;
FDCOUT:
    OUT (FDC_COMMAND_REG),A
;   LD A,30H
    LD A,50H
WLOOP: DEC A
    JR NZ,WLOOP
LOOP2:
    IN A,(FDC_STATUS_REG)
    BIT 0,A ; BUSY IS CLEAR?
    JR NZ,LOOP2
    RET
 

以上です。

SORD M23へのCP/M移植手順メモ その1(ソースコードとその他のツールの入手)

 

CP/Mの入手


cpm2-asm.zipと、cpm2-plm.zipを入手する。


CBIOS.ASMをZ80表記にする。

 

CBIOS.ASMはcpm2-plmのディレクトリ内にある。まずTOZ.EXEを入手する。ターミナル画面からMS-DOS playerを使って以下のように入力する。

 

> msdos.exe TOZ.EXE CBIOS

 

これでZ80表記のCBIOS.MACが生成される。CBIOS.Z80とかにリネームすると便利。


CP/Mシステムソースコードを修正する

cpm2-asmディレクトリの中にあるCPM22.Z80アセンブラによってはエラーが出るので修正する。

 

1284行の以下の文を、21行目のTBASE~の下に挿入する。

NFUNCTS EQU 41

 

367行目の以下の文を修正する。

JP NZ,HALT

JP NZ,HLT

 

674行目の以下の文を修正する。

HALT:    LD HL,76F3H

HLT:    LD HL,76F3H

 

2043行目の以下の文を修正する。

CHKSUM1:ADD A,M

CHKSUM1:ADD A,(HL)

 

3705行目の以下の文を修正する。

CKSUMTBL: DEFB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

CKSUMTBL: DEFW 0
          DEFB: 0,0,0,0,0,0,0,0,0,0,0,0,0,0

 

3709行目の以下の文を修正する。

DEFB    0,0,0,0

DEFB    0

以上の修正で、ZASM.EXEアセンブルできる。

ZASM.EXEはHEX出力なので、BINに変換する必要がある。hex2bin.exeで変換できる。

AILZ80ASM.EXEを使う場合

更に、WindowsネイティブなアセンブラであるAILZ80ASM.EXEを利用するためには、以下の修正を行う。

2169行目、3341行目、3344行目の以下の文を修正する。

SBC A,M

SBC A,0

 

更に先ほど変更した3705行目を更に変更する(DEFBの次の「:」を取る)。

CKSUMTBL: DEFW 0
          DEFB: 0,0,0,0,0,0,0,0,0,0,0,0,0,0

CKSUMTBL: DEFW 0
          DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0

 

これで、AILZ80ASM.EXEでも動作するアセンブラリストになる。またAILZ80ASM.EXEはオプションでBIN出力があるので、ZASM.EXEよりも作業が一つ減る。

このバイナリで実行するとディスク周りにバグが入ります。問題ないことを確認しました。

CP/Mのメモリモデルの選択

 

20Kモデルなら、CPM22.Z80の14行目の以下の文のようにする。

 

MEM EQU 20

 

まずは20KBモデルを選択する方が無難。より大きなモデルにするのは簡単。

 

BIOSを書く


ディスクread/writeルーチンは、DMA転送なしのバージョンを単体の機能だけのプログラムを書いて、うまく動いたら、次にDMA転送ありで書くと着実。最後にCP/Mに実装する。

 

hstbufアドレスとDMAが利用するI/Oバッファアドレスを一致させる

DMACが読み書きするメモリエリア(I/Oバッファ)の位置に注意。このI/Oバッファのアドレスは、CP/Mのホストアドレスバッファhstbufに一致させる必要がある。これをやらないと、ディスクデータとCP/M間でデータのやり取りができなくて、DIRコマンドの出力が全て空欄になる。

具体的にはBIOS.Z80の後半にある以下の文

  5230                    erflag:        DS    1    ;error reporting
  5231                    rsflag:        DS    1    ;read sector flag
  5232                    readop:        DS    1    ;1 if read operation
  5233                    wrtype:        DS    1    ;write operation type
  5234                    dmaadr:        DS    2    ;last dma address
  5236                    hstbuf:        DS    hstsiz    ;host buffer

この最下行のhstbufのアドレスとDMAコマンドチェーンの36H,52Hは同じである必要がある。書き込み時のDMAコマンドチェーンも同様。

DMA_COMMANDS:
    DB 15H,0C3H,0C3H,0C3H,0C3H,03CH,0C3H
    DB 0BBH,01H,9BFH
    DB 6DH
    DB 0C3H,0FFH,00H,02CH,010H,08DH
    DB 36H,52H ; this address is hstbuf address !!!!
    DB 9AH
    DB 0CFH,87H


蛇足だが、hstbufのアドレスの確認はアセンブル時にlistファイルの出力をONにしておき、 listファイルを確認して行う。つまり、確認の為に一度アセンブルし、DMAのI/Oバッファアドレスを修正してもう一度アセンブルする必要がある。

CP/MでDMAというと関連書籍やソースコードで80H番地をよく見るが、内部的に使っているだけなのでBIOSを書くうえでは無視して良い。

 

ブロッキング/デブロッキング実装のタイミング


個人的には、まずは単密度(128バイト/セクタ)でディスクイメージを作って、ブロッキング/デブロッキングなしで、一度移植を行なって問題なく動いたら、その後、倍密度(256バイト/セクタ)でブロッキング/デブロッキングを実装するのが理想と思われる。

 

SORD M23のフロッピーディスクの制御(WRITE編)

WRITE編です。これもSORD M68のときとほぼそのままです。

DMAコマンドチェーンは以下の通りです。

DMA_WRITE_COMMANDS:
    DB 16H
    DB 0C3H,0C3H,0C3H,0C3H,0C3H,0C3H
    DB 83H ; STOP DMA
    DB 79H ;
    DB 00H,020H ; source memory address
    DB 00H,0FFH ; byte number of transfer
    DB 14H,28H,8DH ;
    DB 0C3H,00H ; FDC data register
    DB 8AH
    DB 0CFH,05H
    DB 0CFH,87H

 

SORD M23のフロッピーディスクの制御(READ編)

SORD M23のFloppy Disk ControllerはMB8877A(FD1771)です。これはSORD M68と同一ですので、以前、CP/Mを移植したルーチンがほぼそのまま利用できます。

I/Oアドレスは以下の通りです。

FDC_COMMAND EQU 0C0H
FDC_STATUS  EQU 0C0H
FDC_TRACK   EQU 0C1H
FDC_SECTOR  EQU 0C2H
FDC_DATA    EQU 0C3H
DMA         EQU 0C4H
FDC_CONTROL EQU 0C5H
DMA_BANK_SEL    EQU 0C6H

 

M68と異なっているのは、ドライブセレクトなどFDDを外的にコントロールしていると思われるポートで、これは完全に異なっているので変更が必要です。といっても、

 

LD (FDC_CONTROL), 01H

 

と1を入れるだけで、ドライブ1、倍密度が選択されます。

DMA転送のREADコードは以下のような感じです。

 

;
; DMA setting & FDD read FOR SIDE 0
; C is Sector No.
; D is Control word.
;
GO_DMA_AND_READ0:
    LD A,C
    OUT (FDC_SECTOR),A
    LD HL,DMA_COMMANDS
    CALL DMA_ON
    AND 20H
    LD A,80H ; READ DATA COMMAND for Side 0
DO_FDC0:
    CALL FDC_OUT
    AND 0FCH
    RET
 

 

Side0とコメントにありますが、SORD M23のFDDは片面ですので、Side0しかありません。

DMAコマンドチェーンを以下に記載します。

DMA_COMMANDS:
    DB 15H,0C3H,0C3H,0C3H,0C3H,03CH,0C3H
    DB 0BBH,01H,0BFH
    DB 6DH,0C3H,0FFH,00H,02CH,010H,08DH
    DB 00H,00H
    DB 8AH
    DB 0CFH,87H

 

SORD M68のときとやや異なりますが、本質的には一緒です。

 

 

 

 

SORD M23のキーボード

SORD M23のキーボードの仕組みについて調べました。

 

M23のキーボードはI/Oポートe0~efに割り当てられています。何かキーを押すと、このポートのどれかに04h、08h、10h、20h、40hが入ります。

 

I/Oポートe0~efとこの値はキーの物理的に位置によって決まります。もちろん特殊キーは下の画像の関係には従いません。

 

I/Oポートとその値の関係(例外あり)

 

M23用のワードプロセッサのキー入力周辺のコードではかなり複雑な計算をして、画面に表示する文字を決めています。これは、QWERTY配列があったりAZERTY配列があったりと国ごとにキー配列が異なるのでそれに対応するため、また、一対一対応でコードを書くとメモリを食いすぎるためだと思われます。

 

今回は、とにかく動くか確かめたかったので、計算のコードを解析するのは後回しにして、このキーはこの文字という一対一対応のコードを書いて、前回の画面に文字を出すコードと組み合わせることで、「キーを押すとその文字が画面に出る」プログラムを書きました。リターンキー(現代のPCではENTERキー)の処理もしてあります。

 

 

SORD M23の画面に文字を書く

Takeda氏が解析してくださったおかげで、色々なことが容易になりました。

 

今回は文字を表示します。

 

SORD M23のCRTCはHD46505SでBOOT ROM内で、80桁、25行に設定されています。

テキストVRAM(文字コード)はF800hからFFFFhまで、テキストVRAMのアトリビュートはF000hからF7FFhまでです。アトリビュートの設定はBOOT ROMでされているので、特に変更する必要がなければ、テキストVRAMの文字コードエリアにアスキーコードを書けば表示されます。テキストVRAMの文字コード領域は、画面に見える範囲は以下のようになっています。

SORD M23のテキストVRAM(文字コード)

ただ、このテキストVRAMはRAMページ1にあり、SORD M23ではI/Oポート0xD2hに任意の値を入力した命令の次の命令がRAMページ1への書き込み/読み込みとなります。0xD2には何を入力しても良いようなので、書き込む文字コードを書き込んでいます。

 

PUTCHR:
    LD A,(HL)
    OR A
    RET Z
    OUT (0D2H),A
    LD (DE),A
    INC HL
    INC DE
    JR PUTCHR

 

DEにテキストVRAM(文字コード)領域のどこかのアドレスが入ります。HLは表示したい文字列の先頭アドレスです。

 

これにキャリッジリターンやラインフィードを実装すると、こんな感じに表示できます。