ちょっとだけ、BIOSの移植が進んだのでメモしたいと思います。

BIOSを移植するにあたり、実機での確認が不可欠と思いますが、それを行うには、CP/Mのシステムを実機のメモリに書き込みしなくてはいけません。
CP/MのシステムはCCPとBDOS及びBIOSですが、BIOSはその機器に依存するので、今回のように書き直しが必要です。CCPとBDOSは基本的に手を加える必要はないはずです。たぶん^^

ということで、ちょっとずるですが! 、CCPとBDOSのバイナリを探してHEXフォーマットに変換して、モニタのLコマンドで読み込みをする方法でCCPとBDOSを実メモリに読み込みたいと思います。

さて、CCPとBDOSのバイナリーの在りかですが、先輩諸氏のブログを参考にさせていただきました。

CPM BIOS編1 で 紹介したサイトの「Digital Research Binary Files」「OPERATING SYSTEMS」から  CP/M 2.2 のCP/M2.2 BINARY をダウンロードします。cpm22-b.zipというファイルでダウロードされますので、解凍します。解凍したフォルダーの中から CPM.SYSというファイルを使用します。
このCPM.SYSというファイルにはCCPとBDOSとBIOSが一緒にパッケージされているようです。

このCPM.SYSのメモリ配置は下記のようになっています。

CP/Mにはメモリサイズにより、CCP,BDOS、BIOSの配置が異なるようで今回のCPM.SYSのメモリサイズは、 62K CP/Mになるようです。

さて、HEXファイルへのコンバートですが、HEXファイルにはロードアドレスが必要になります。 今回の62K CPMでは 0xDC00となります。
コンバートを行うソフトですが今旬なPythonを使うことにします。

Pythonで記述されたIntelHexというライブラリーがあり、その中にオブジェクトをHEXコードに変換する実行コマンドが含まれています。

では早速インストールしたいと思います。(今まで通りRaspberryPiのRaspbianでの環境で確認しています。)

ライブラリのインストール
pythonのパッケージ管理コマンドのpipコマンドでインストールします。
$ sudo pip install intelhex

cpm.sysをHEXファイルに変換します。ロードアドレスは0xdc00とします。
コマンド名は bin2hex.py オフセットアドレス、入力ファイル、出力ファイルを順に指定します。ここでは出力ファイル名としてcpm.hexとしました。

$ sudo python /usr/local/bin/bin2hex.py --offset=0xdc00 CPM.SYS cpm.hex

前回に作成しているRAM64Kモニタで、tコマンドで64Kメモリに切り替えてから、lコマンドで先ほどのcpm.hexを読み込みます。0xdc00以降にccp、bdos、biosと書き込まれます。

biosは今回のシステムでは書き換えが必要なので、シリアル通信が確認できるようにシリアル関連のみコードを追加しました。またCCPに制御を渡すまでのbootについてもコードを追加してみました。

BIOSの先頭アドレスには、jp bootが配置されてるので、無条件でbootに飛んできます。 boot:では仮のスタックポインターをDMA buffer ariaの高位アドレスに設定しています。そのあと、シリアルとPIOをイニシャライズしています。その後、サイズとバージョンを表示し、login disk No.を0x00(つまりA:)に
I/O Byte に0x00に設定しています。そのあと gocpmに飛びます。

gocpm:では 0x0000から3バイトに wbooteにジャンプするように設定しています。その後、BDOSのコール先を設定しています。
login disk No. をCレジスターにセットして、ccpにジャンプしています。

const: conin: conout:の標準入出力と readerとlist:、punch:は標準入出力にて代用しています。

その他のルーチンは単なるretのみで帰っていきます。

ディスク関係はエラーになりますが、標準入出力関係の確認をBDOSをコールして確認ができそうです。

下記の仮のBIOSをアセンブルします。

;;z80 (TMPZ84C015) 62K cp/m V2.2 BIOS by Pinecone 2020/02/02

; TMPZ84C015 cpu
; ram 0000h -- ffffh
; External clock 20MHz


; TMPZ84C015 serial communication (CH-B)
; extemal Clock 614.4KHz(38.4Kpbs)
 
; assembler
;  program start 0xF200
;  main          0xF200
;
; assemblers  ASxxxx and ASlink V5.10
; file name bios202.asm
; $ asz80 -l -s -o bios202.asm
; $ aslink -i bios202
; $ tmpz84_moni71 l command Hex load jump 0xf200


        .z80

VERS    .equ    22              ;Version 2.2

MSIZE   .equ    62              ;CP/M memory size 
        
BIAS    .equ    (MSIZE-20)*1024
CCP     .equ    0x3400 + BIAS   ;base of cpm console processor
BDOS    .equ    0x806 + CCP     ;basic dos
BIOS    .equ    CCP + 0x1600    ;BIOS
CDISK   .equ    0x0004          ;disk number 0=A 1=B ..
IOBYTE  .equ    0x0003          ;intel i/o byte

cpmboot .equ    CCP

;; TMPZ84C015 serial port SIO-B CH
SIOBD   .equ    0x1A            ;SIO-B CH DATA REG
SIOBC   .equ    0x1B            ;SIO-B CH CONTL REG
;; TMPZ84C015 pio port  PIO-A CH
PIOAD           .equ    0x1c            ;PIO-A CH DATA REG
PIOAC           .equ    0x1d            ;PIO-A CH CONTL REG
;; TMPZ84C015 pio SPI OUT-PORT PIO-A CH
S_DI            .equ 7 ;0b10000000 D7
S_CS            .equ 6 ;0b01000000 D6
S_CLK           .equ 5 ;0b00100000 D5
;; TMPZ84C015 pio SPI INPUT-PORT PIO-A CH
DO              .equ 0 ;0b00000001 D0

BUFF_ADDR       .equ    0x80    ;default buff address

        .area   BIOS(ABS)

        .org    BIOS

;NSECTS .equ    (#. - CCP)/128  ;warm start sector count

;;      jump vector for indiviual routines
;
        jp      boot            ;cold start
wboote: jp      wboot           ;warm start
        jp      const           ;console status
        jp      conin           ;console character in
        jp      conout          ;console character out
        jp      list            ;list character out
        jp      punch           ;punch character out
        jp      reader          ;reader character out
        jp      home            ;move head to home position
        jp      seldsk          ;select disk
        jp      settrk          ;set track number
        jp      setsec          ;set sector number
        jp      setdma          ;set dma address
        jp      read            ;read disk
        jp      write           ;write disk
        jp      listst          ;return list status
        jp      sectran         ;sector translate

;;
;;     IBN-COMPATIBLE 8 Inch DISKS
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;       disk Parameter header for disk 00
dpbase: .dw     trans, 0x0000
        .dw     0x0000, 0x0000
        .dw     dirbf, dpblk
        .dw     chk00, all00
;       disk parameter header for disk 01
        .dw     trans, 0x0000
        .dw     0x0000, 0x0000
        .dw     dirbf, dpblk
        .dw     chk01, all01
;       disk parameter header for disk 02
        .dw     trans, 0x0000
        .dw     0x0000, 0x0000
        .dw     dirbf, dpblk
        .dw     chk02, all02
;       disk parameter header for disk 03
        .dw     trans, 0x0000
        .dw     0x0000, 0x0000
        .dw     dirbf, dpblk
        .dw     chk03, all03
;
;       sector translate vector
trans:  .db      1,  7, 13, 19  ;sectors  1,  2,  3,  4
        .db     25,  5, 11, 17  ;sectors  5,  6,  7,  6
        .db     23,  3,  9, 15  ;sectors  9, 10, 11, 12
        .db     21,  2,  8, 14  ;sectors 13, 14, 15, 16
        .db     20, 26,  6, 12  ;sectors 17, 18, 19, 20
        .db     18, 24,  4, 10  ;sectors 21, 22, 23, 24
        .db     16, 22          ;sectors 25, 26
;
dpblk:  ;disk parameter block, common to all disks
        .dw     26              ;sectors per track
        .db     3               ;block shift factor
        .db     7               ;block mask
        .db     0               ;null mask
        .dw     242             ;disk size-1
        .dw     63              ;directory max
        .db     192             ;alloc 0
        .db     0               ;alloc 1
        .dw     16              ;check size
        .dw     2               ;track offset
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;       disk port and commands
lf      .equ    0x0a
cr      .equ    0x0d

signon:                         ;signon massage ??K cp/m  ?.?   
        .db     cr,lf,lf
        .db     MSIZE/10+"0",MSIZE % 10 +"0"
        .str    "K CP/M VERS "
        .db     VERS/10+"0",".",VERS % 10 +"0"
        .db     cr,lf,0

boot:
        ld      sp,BUFF_ADDR+0x80
        call    init_io
        ld      hl,signon
        call    prmsg
        xor     a
        ld      (CDISK),a
        ld      (IOBYTE),a
        jr      gocpm

wboot:
        ret


gocpm:                          ;set default buff address to 0x80
        ld      bc,BUFF_ADDR
        call    setdma

        ld      a,0xc3          ;jump wboot address set at 0x0000
        ld      (0x0000),a
        ld      hl,wboote
        ld      (0x0001),hl

        ld      (0x0005),a      ;jump BDOS address set at 0x0005
        ld      hl,BDOS
        ld      (0x0006),hl

        ld      a,(CDISK)
        ld      c,a
        jp      cpmboot

prmsg:
        ld      a,(hl)
        cp      0x00            ;massage end ?
        ret     z
        ld      c,a
        call    conout
        inc     hl
        jr      prmsg

const:                          ;console status
        ld      a,0xff          ;READY= 0xff BUSY=0x00 out Areg
                ret
conin:                          ;console character in
reader:                         ;reader character out
        jp      ci              

conout:                         ;console character out
list:                           ;list character out                     
punch:                          ;punch character out
        push    af
        ld      a,c
        call    co
        pop     af
        ret
home:   
        ret
listst:                         ;return list status
        ld      a,0x00
        ret
sectran:                        ;sector translate
        ret
setdma:                         ;set dma address set bc reg
        ret
seldsk:                         ;c reg set disk no
        ret
settrk:                         ;set track address given by c
        ret
setsec:                         ;set sector numbar given by c
        ret
read:                           ;read next disk record(assuming disk/trk/sec/dma set)
        ret
init_io:                        ;tmpz84c015  serial siob ch/pio-a ch/spi-init
        call    siobinit
        call    pioainit
;       call    init_spi
        ret

write:
        ret


ci:
        in      a,(SIOBC)
        bit     0,a
        jr      z,ci
        in      a,(SIOBD)
        ret
co:
        push    af
com_out01:
        in      a,(SIOBC)
        bit     2,a
        jr      z,com_out01
        pop     af
        out     (SIOBD),a
        ret
        
siobinit:
        ld      b,12
        ld      hl,SIO_init_data
siobinit01:
        ld      a,(HL)
        out     (SIOBC),a
        inc     hl
        djnz    siobinit01
        ret

pioainit:
        ld      b,3
        ld      hl,PIO_init_data
pioainit01:
        ld      a,(HL)
        out     (PIOAC),a
        inc     hl
        djnz    pioainit01
        ret     

SIO_init_data:
        .db     0x00,0b00110000         ;WR0=WR0:set ,WR0: err reset
        .db     0x01,0b00000000         ;WR0=WR1:set ,WR1: all int reset
        .db     0x02,0b00000000         ;WR0=WR2:set ,WR2: CH-B int set
        .db     0x03,0b11000001         ;WR0=WR3:set ,WR3: RxBit=8bit Rx=ready
        .db     0x04,0b01000100         ;WR0=WR4:set ,WR4: clck=exIN*1 stop=1bit parity=non
        .db     0x05,0b11101010         ;WR0=WR5:set ,WR5: char=8bit hardware flow=non Tx=ready
                         
PIO_init_data:
        .db     0b11001111              ;PIOAC:set 0xcf: Mode3 (bit mode)
        .db     0b00011111              ;PIOAC:set 0x1f: D4-D0=input D7-D5=output
        .db     0b00000000              ;PIOAC:set 0x00: interrupt disables


  
track:  .ds     2               ;two bytes for expansion
sector: .ds     2               ;two bytes for expansion
dmaad:  .ds     2               ;direct memory address
diskno: .ds     1               ;disk number 0-15
;
;       scratch ram area for bdos use
;begdat equ     $               ;beginning of data area
dirbf:  .ds     128             ;scratch directory area
all00:  .ds     31              ;allocation vector 0
all01:  .ds     31              ;allocation vector 1
all02:  .ds     31              ;allocation vector 2
all03:  .ds     31              ;allocation vector 3
chk00:  .ds     16              ;check vector 0
chk01:  .ds     16              ;check vector 1
chk02:  .ds     16              ;check vector 2
chk03:  .ds     16              ;check vector 3

アセンブルしたbios202.hexをモニタのlコマンドで、先ほどcpm.hexのbiosを上書きします。(モニタはMonitor TMPZ84C015 CPU ver0.72(SPI) by Pinecone 2019/9/6 で確認しました。)

jコマンドで 0xf200に飛びます。
下記の表示がでます。(0xf200に飛んだあと、Enterを押しています。)

>j f200 y:                                                                      
                                                                                
                                                                                
                                                                                
62K CP/M VERS 2.2                                                               
                                                                                
                                                                                
                                                                                
Bdos Err On A: Select

BDOSでエラーになっています。ディスク関係のルーチンがないので当然ですね^^

BDOSの確認ができそうなので、次回はシリアル関係のBDOSコールの確認プログラムを作成して、見たいと思います。

コメントを残す

BIOS, CP/M, TMPZ84C015, Z80の関連記事
  • Z80(KL5C80B12C)に萌えたい。5-BIOS完成
  • Z80(Z80+SIO+PIO)に萌えたい。7-BIOS完成
  • Z80(Z80+8251+8255)に萌えたい。9-BIOS完成
  • Z80に萌えたい CP/M ディスク書き込み改善
  • Z80(Z8S180)に萌えたい。Z8S180でも容量拡張BIOS
  • Z80に萌えたい CP/M ディスクアクセス改善
おすすめの記事
Z8S180
内蔵タイマーの確認を行ってみました。 内蔵タイマーは2チャンネルありますが、ここでは1チャンネルだけでLED 点滅(といっても 20mSの速...
monitor
TMPZ84C015を使用したAKI-80ボードに以前作成したZ8S180用モニタを移植してみました。 移植したZ8S180用モニタは、メモ...