SHARP X68000にCP/M-68Kを移植しようと思います。
開発環境
エミュレータ
xm6gを使用しました。X68000で最強と噂されるエミュレータです。デバッグ機能は操作が直感的で痒い所に手が届く素晴らしいソフトウェアです。
CP/M-68Kのソースコード
68kv1_2.zipを使用しました。後に68kv1_3.zipへアップグレードしました。
アセンブラ
MSDOS用のAS68K.EXEを使用しました。出力はS2レコードなので、RAWバイナリに変換する必要があります。MOT2BIN.EXEを使用しました。
AS68K.EXEは制限が多く、MS-DOSプレイヤーが必要ということで使い勝手が今一つだったので、LEA MACRO ASSEMBLERに変更しました。RAWバイナリ出力ができるので、MOT2BINも必要ありません。
また、ブートローダーだけは、xdev68kのコマンド一群を使いました。
ディスクイメージの操作
l3diskexを使用しました。
1. CP/MのBIOS以外の部分をRAWバイナリにしておく
68kv1_2.zipを展開して、DISK7フォルダ内のCPM15000.SRをMOT2BINでRAWバイナリ(ここではCPM15000.BINとします)に変換します。
CPM15000.MAPを見て、_cppが$150B8であること、_initが$1B000であることを確認します。つまりBIOSは$1B000から始まります。CPM15000.BINを見ると、$1B000よりだいぶ手前で切れているので、そこまでFFで埋めます。
以後、作成したBIOSは、$1B000以降に張り付けることで、CP/Mのシステム(名前も何でもよいはず。便宜上CPM.SYSまたはcpm68k.sysとしている)となります。
自分でブートローダーを書くなら、ディレクトリトラック以外ならどこにシステムを置いても動くと思います。一般に、ディレクトリのトラックは第2トラックです。
2. ディスクイメージを作る
CP/Mのデフォルトでは、ディスクのトラック0、サイド0は単密度(FM)記録であることを期待しています。
しかし、どうやらX68000のIPLはトラック0、サイド0が倍密度(MFM)記録であることを前提としているようです。実際、単密度のディスクで起動を試みましたが失敗しました。
この制限の為に、他のCP/Mのディスクイメージを転用できません。一からディスクイメージを構築します。
3. l3diskexの設定ファイルを変更する
l3diskexディレクトリ直下のdataディレクトリ内の二つのファイル(basic_types.xml、disk_types.xml)を変更します。
私も詳細不明なままいじっているのでよくわからない点もありますが、以下のようにするとCP/Mで使えるディスクイメージが作れます。
basic_types.xmlに以下の項目を加えます。
disk_types.xmlに以下の変更を加えます。具体的には”CPM68-2HD-X68"を加えただけです。
このディスクの設定は、1024byte/sector,8sector/track,77track,2sideとなっています。これはHuman68kと同じです。
この方法でイメージを作った時の欠点は、CP/MのBIOSに必須のディスクパラメータブロック(DPB)のパラメータが、ディスクイメージを調べないと分からない点です。一度、このイメージを作成して、なんでも良いのでファイルをドラッグアンドドロップして、プロパティにある占有しているブロック数をみると、1ブロックが何バイトなのか分かります。このディスクイメージでは、1ブロックが8192バイトでした。DPBについては別項で書きます。
4. ブートローダーを書く
XM6GはRAWバイナリを任意のメモリに書き込んでそこから実行を開始するという機能はないようなので、ディスクイメージにブートローダーを書き込んで、そこから自分のプログラムを動かす必要があります。
このWEBサイトを参考にしました。
X68000は起動するとドライブ0のトラック0、サイド0、セクタ1から1セクタ分1024byteを読み、$2000番地に書き込んで、$2000から実行を開始します。
ブートローダーの機能は、CP/Mシステムをメモリに書き込んで、CP/Mシステムのinitにジャンプすることです。
今回はメモリの$15000番地からシステムが始まるバイナリを選んだので、ディスクから読み込んだシステムを$15000に書き込みます。
次のようなコードにしました。IOCSを使っています。アセンブルは、xdev68kのものを使いました。
l3diskexにCPM.SYSをドラッグアンドドロップしたら、トラック3、サイド0から配置されたので、そこを読むように書いてあります。
この辺、作業が前後します。ブートローダーを書く前に、文字表示とキー入力を書いたBIOSからCPM.SYSを作って(リードライトルーチンは空にしておきます)、ディスクイメージに書き込みます。この時、l3diskexがどこ書き込むか知る必要があります。希望の場所に書き込ませる方法を筆者は知りませんので、こんなやりかたになってしまっています。
CP/M-68Kのシステムは約25kBなので、4回トラックの読込を繰り返せば良いことになります。
注意すべきなのはブートローダーが最後にジャンプする番地は、BIOS内のinit($1B000)だと言う点です。システムの先頭($15000)ではありません。
5. BIOSを書く
CP/M-68Kのソースコード群には色々なBIOSがあって、どれが良いのか迷いますが、今回はDISK7ディレクトリのERGBIOS.Sをひな形にしました。もっともシンプルで理解しやすい内容です。その他には、CP\M-68KのシステムガイドのAppendixにあるサンプルBIOSもシンプルで良いと思います。
最初にcppの位置を明確にします。番地はSR15000.MAPに書いてあります。
_ccp: equ $150bc
BIOSに文字表示とキー入力ルーチンを書く
文字表示とキー入力部分を書きます。IOCSを使うので簡単です。
AS68K.EXEでアセンブルします。SレコードファイルをMOT2BINでRAWバイナリに変換し、前半のゴミ部分をカットしたものを、FFで所定の領域を埋めたSR15000.BINの末尾に加えます。
ここまで出来れば、エミュレータ上でディスクを起動して、画面に起動画面が出ます。
次はディスク周りの内容です。