CP/M-68Kを移植していく Part 2
CP/M の入手先
OPERATING SYSTEMS に、CP/M-68K 1.3 のバイナリがあります。
ZIPを解凍したら9個のディスクイメージが得られます。DISK8の中にある CPM15000.SR が、CCP と BDOS をまとめたものです。これにBIOSを作ってリンクすれば、移植はOKのはずです。リンクに必要なアドレスは、同じディスクイメージ中の CPM15000.MAP を参照すると得られます。
バイナリデータを取り出す
CPM15000.SRは、モトローラSレコードフォーマットです。バイナリデータを得るには変換ツールが必要なわけですが、よくわからなかったので、Wikipedia でSレコードの情報を調べて Python で変換ツールを作りました。
#! /usr/bin/env python3
import sys
args = sys.argv
if len(args) != 3:
print('Usage : sr2bin srfile binfile')
exit(1)
inf = open(args[1], 'r')
lines = inf.readlines()
outf = open(args[2], 'wb')
# S record format
# S2 24 015000 4EF9000150504EF90001504A2043502F4D2D36384B2056312E3320434F505952 F6
addr = 0
dsize = 0
data = ''
for rec in lines:
type = rec[:2]
size = int(rec[2:4], 16)
if type == 'S2':
data = rec[10:10 + size * 2 - 8]
dsize = len(data) // 2
elif type == 'S9':
break
for offset in range(dsize):
bdata = int(data[offset * 2:offset * 2 + 2], 16).to_bytes(1)
outf.write(bdata)
addr += 1
for offset in range(0x6000 - addr):
outf.write(0xff.to_bytes(1))
inf.close()
outf.close()
この変換ツールはかなり手抜きで、アドレスは連続していると仮定し、チェックサムも確認せずゴリゴリ変換します。変換の最後に、サイズが24576バイトになるように後ろに0を埋めています。これはリンクに都合が良いためです。
BIOS とのリンク
CPM15000は、メモリ上で0x15000から配置される CCP + BDOS です。 CPM15000.MAP を見てみると、下のようになっています。
_submit 1A244 global bss
_morecmd 1A246 global bss
_autost 1A1BE global bss
_usercmd 1A1BF global bss
_ccp 150BC global text
_patch 1A248 global bss
cpm 15000 global text
_bdos 150CA global text
:
:
_init 1B000 equ global abs
:
cpm のアドレスが 0x15000 になっています。リンクに重要なのは、BIOSの先頭アドレスの_init と、CCPのエントリポイントの_ccp です。ちょっとまだ確証はないのですが、BIOSは、0x1B000 から始まり、WARM BOOT で _CCPにジャンプするコードを書くだけでOKのようです。
先のSレコードからバイナリデータに変換するコードで、24576バイトに調整しているのは、CPM15000 と BIOS とのリンクを単純にファイル結合だけで済むようにできるからです。
CP/M-8000 を移植したときの苦労を考えると、ちょっと信じられないくらい簡単なので、本当にこれだけなのか?まだ確証が持ててないのですが。