CP/M v2.23
概要
Sharp MZ80A 向けの CP/M バージョンは Micro Technology によって作成されましたが、80 桁スクリーンがないため、アップグレードなしではあまり役に立ちませんでした。調査したところ、Kuma などのサードパーティが 80 桁アップグレードを開発し、後に SUC から入手できるようになりましたが、MZ80A の CP/M は 2020 年時点では多くの記事で言及されているものの、実際に入手するのは非常に困難でした。original.sharpmz.org などの優れたサイトは 80K/80B/800 バージョンを提供していますが、MZ80A 向けは提供していません。
80 桁カラーアップグレードボードと Rom Filing System を開発した主な目的は、MZ80A で CP/M を実現することでした。FPGA ベースのハードウェアエミュレータープロジェクトでは様々な桁数の出力、カラー、グラフィックスに対応する変更を簡単に追加できますが、ヴィンテージマシンへの変更を最小限に抑えた実際のオリジナルハードウェアで行うことは、より大きな挑戦であり、1983 年にこのマシンを初めて手にして以来の個人的な願望でもありました。過去のアップグレードのほとんどはオリジナル PCB へのカットやリンクが必要ですが、私は特にそれをしたくありませんでした。Sharp が作ったままのオリジナルハードウェアを保ちたいのです!オリジナル PCB への私の唯一の変更は、チップ(IC8 74LS165 ビデオシフトレジスター)をソケット化することで、これは使用中に故障して交換が必要になった場合でも簡単に行え、マシンは 100% オリジナルの状態に保たれ、元の工場出荷状態に簡単に戻せます。
こうして CP/M を動作させようとしましたが、ネット上に大量の情報があっても簡単な作業ではありませんでした。まず、MZ80A 向けの Micro Technology 版 CP/M の入手が非常に困難だったため、MZ80K と MZ80B バージョンに頼ることにしました。次に、MZ80A が反転データを読み取るように設計されているという奇妙なディスクフォーマットの問題に直面しました。長い話を短くすると、独自の ROM ベース版 CBIOS を作成し、CP/M v2.23 の BDOS+CCP と組み合わせることにしました。このセクションではその作業の詳細を説明します。
CP/M ブートプロセス
CP/M の起動は 2 つのフェーズで行われます:
- オリジナルの AFI フロッピーディスク制御ソフトウェアを使用して反転ブートセクターを読み込み、0x0000 に制御コード 0x02 + “IPLPRO” が含まれていることを確認し、カプセル化されたブートローダーに制御を渡す
- 0x9C00 から始まる CCP、BDOS、CBIOS を読み込む。CBIOS が制御を引き継ぎ、異なるディスクフォーマットを適用して異なる FDC コントローラーロジックを使用する(データを再反転する)。
MZ80A 版の CP/M を持っていなかったため、MZ80K バージョンを読み込もうとしましたが、非反転データのため MZ80K ブートディスクを MZ80A フォーマットに変換する必要がありました。変換後に CP/M を起動しようとしましたが、ディスクコントローラーなどの非互換性がありました。その後 Micro Technologies の CP/M の MZ80B と MZ800 バージョンを調べましたが、これらも異なるディスクフォーマットを使用しており、最終的にはカスタム CP/M を構築して独自の CBIOS を作成するのが最善のアプローチだと判断しました。
CBIOS
3 つのコンポーネントはすべてフロッピーディスクからブートストラップされ、メモリ(MZ80K/A では 0x9C00)に読み込まれ、制御が CBIOS に渡され、CBIOS がマシンをセットアップしてから CCP に制御を渡します。通常の動作条件下では、読み込まれたアプリケーションは BDOS を呼び出して、コンソールへの書き込み、キー入力の取得、ディスクアクセスなどのサービスを明確に定義された API から利用しますが、BDOS サービスが不要な場合は CBIOS を直接呼び出してその API を使用し、CCP+BDOS の RAM を使用して追加のプログラムスペースを確保することができます。アプリケーションが完了すると、ベクター 0x0000 にジャンプして CCP+BDOS の再読み込みを含むウォームスタートが開始されます。
CP/M は自己修正/組み込み変数を使用するため ROM への格納には適していませんが、CBIOS については話が別です。CBIOS を ROM に配置して RAM を増やすことが可能で、ページ ROM バンクを持つ Rom Filing System にアクセスできることもあり、私はこの方法を採用しました。
CBIOS を作成するには、以下の API メソッドを提供する必要があります:
| API メソッド | 説明 |
|---|---|
| BOOT | コールドスタート。CCP を呼び出す前にすべてのハードウェアを初期化する。 |
| WBOOT | ウォームスタート。ハードウェアの変更を元に戻してから CCP を呼び出す前に CCP+BDOS を再読み込みする。 |
| CONST | コンソールステータス。キーボードのキー入力が待機中かどうかを確認する。 |
| CONIN | コンソール入力。キーボードからキーを取得し、利用可能でない場合は待機する。 |
| CONOUT | コンソール出力。画面に文字を出力する。 |
| LIST | リストデバイス出力。リストデバイス(例:プリンター)に文字を出力する。 |
| PUNCH | パンチデバイス出力。パンチデバイス(70年代にはパンチテープやカードが使われていた)に文字を出力する。 |
| READER | リーダー入力。リーダーデバイス(例:紙テープ)から文字を入力する。 |
| HOME | 現在選択されているディスクのヘッドをトラック 0 に移動する。 |
| SELDSK | ディスクを選択/有効化する。 |
| SETTRK | 次の読み書き操作のディスクトラックを設定する。 |
| SETSEC | 次の読み書き操作の選択されたトラック上のディスクセクターを設定する。 |
| SETDMA | データが読み書きされる場所のディスクメモリアドレスを設定する。 |
| READ | ディスクセクターを読み取る。 |
| WRITE | ディスクセクターに書き込む。 |
| LISTST | リストデバイスステータス。リストデバイスが新しい文字を受け入れる準備ができているかを確認する。 |
| SECTRN | セクター変換。特定のハードウェアへの適応やディスクサブシステムの応答性向上のための論理から物理セクターへの変換。 |
CP/M が提供する基本的な文字入出力メカニズムの上に必要なさらなる要件として、ほとんどのアプリケーションは高度な画面とキーボード機能を提供するスマートターミナルが CP/M マシンの前にあることを期待しています。これは通常 DEC VT52 や VT100 などのターミナルの形式です。MZ80A は独自の画面とキーボードを持っているため、このスマート機能を作成する必要があります。
CBIOS を作成するには、以下のファームウェアサブモジュールをコーディングする必要があります:
| サブモジュール | 説明 |
|---|---|
| 基本画面 I/O | 画面に文字を配置する、画面をクリアするなどの低レベル機能。 |
| 高度な画面 I/O | 表示出力の位置決め、画面の一部のクリア、太字などの特別属性のインテリジェンス。 |
| キーボード I/O | キーコードをスキャンして返し、必要に応じて ASCII にマッピングする。 |
| ディスク I/O | 複数のディスクセクターを読み書きする機能を提供する。 |
すべての機能はスペースを必要とし、以下のように割り当てられています:
| ROM | アドレス | 説明 |
|---|---|---|
| 4K MROM(0x0000 - 0x0FFF から再配置されたモニター ROM) | 0xC000 - 0xCFFF | CBIOS(CP/M API、初期化ルーチン、ROM ディスクコントローラールーチン、割り込みルーチン)を提供。 |
| 2K ページ ROM | 0xE800 - 0xEFFF、バンク 8 | 基本的なサウンドとメロディー、RTC、キーボードとヘルパー機能。 |
| 2K ページ ROM | 0xE800 - 0xEFFF、バンク 9 | 画面 I/O と ANSI ターミナルパーサー。 |
| 2K ページ ROM | 0xE800 - 0xEFFF、バンク 10 | SD カードコントローラー機能。 |
| 2K ページ ROM | 0xE800 - 0xEFFF、バンク 11 | フロッピーディスクコントローラー機能。 |
CP/M ディスクドライブ
ドライブの順序は以下の表に示されています:
| ROM ドライブ # | 存在 | 0 | 1 | 2 | 存在 | 0 | 1 | 2 |
|---|---|---|---|---|---|---|---|---|
| ROM ドライブ | n/a | A | A,B | n/a | A | A,B | ||
| フロッピーディスク | あり | A,B | B,C | C,D | なし | |||
| SD カード | あり | C,D,E,F | D,E,F | E,F,G | あり | A,B,C,D,E | B,C,D,E | C,D,E,F |
| SD カード | なし | あり |
機能
標準的な BIOS 機能に加えて、以下の機能が CBIOS に追加されています。
- 50mS 精度のリアルタイムクロック
- バッファと自動リピートを持つ割り込み駆動キーボード
- 通常、Caps Lock、Shift Lock の 3 モードキーロック
- ANSI ターミナル機能
- 1.44M、720K、320K サイズの再ターゲット可能なフロッピーディスクドライブ
- 240K サイズの再ターゲット可能な ROM ドライブ(設定で変更可能)
- 再ターゲット可能な SD カード 16MB ハードディスク
- SHIFT+GRAPH+BREAK でモニターに終了
CP/M のビルド
これを実現するにはいくつかのツールが必要で、現時点ではかなり手動のプロセスです。
パス
読みやすくするため、以下の短縮名はこの章の対応するパスを指しています。
| 短縮名 | |
|---|---|
| [<ABS PATH>] | このリポジトリがシステムに展開されたパス。 |
| <software> | [<ABS PATH>]/MZ80A_RFS/software |
| <roms> | [<ABS PATH>]/MZ80A_RFS/software/roms |
| <CPM> | [<ABS PATH>]/MZ80A_RFS/software/CPM |
| <tools> | [<ABS PATH>]/MZ80A_RFS/software/tools |
| <MZF> | [<ABS PATH>]/MZ80A_RFS/software/MZF |
| <MZB> | [<ABS PATH>]/MZ80A_RFS/software/MZB |
ツール
Z80 Glass Assembler - アセンブリファイルをマシンコードに変換する Z80 アセンブラー。
samdisk - マルチ OS コマンドライン低レベルディスク操作ツール。
cpmtools - マルチ OS コマンドライン CP/M ディスク操作ツール。
CPMToolsGUI - Windows ベースの GUI CP/M ディスク操作ツール。
z88dk - Z80 CPU 向けの優れた C 開発キット。
sdcc - Z80 をターゲットの一つとする別の優れた Small Device C コンパイラー。z88dk はこのツールの Z80 向け強化版をパッケージ内に提供しています。
ソフトウェア
ソフトウェアイメージのビルドは、リポジトリをクローンし、提供されているシェルスクリプトとバイナリをいくつか実行することで行えます。
| スクリプト | 説明 |
|---|---|
| assemble_cpm.sh | CPM バイナリ、RFS 経由で読み込むための CPM MZF フォーマットアプリケーション、CPM ROM ドライブ 0 と 1 をビルドするシェルスクリプト |
| assemble_rfs.sh | Rom Filing System ROM イメージをビルドする bash スクリプト。 |
| assemble_roms.sh | SA-1510 モニター ROM などの標準 MZ80A ROM をすべてビルドする bash スクリプト。 |
| make_roms.sh | 512KByte フラッシュ RAM にプログラミングするのに適した RFS ROM をビルドする bash スクリプト。 |
| make_cpmdisks.sh | SD カードまたは ROM ドライブのロー形式イメージと CPC Extended Disk Format の CP/M ディスクセットをビルドする bash スクリプト。 |
| make_sdcard.sh | RFS イメージといくつかの CPM ディスクドライブを組み合わせた SD カードイメージを作成する bash スクリプト。 |
| mzftool.pl | MZF イメージを作成/抽出/操作する Perl スクリプト。 |
| processMZFfiles.sh | MZF プログラムのセットを Rom Filing System ROM での使用に適したセクター化イメージに変換する bash スクリプト。 |
| sdtool | src/tools リポジトリで作成されたバイナリ。RFS SD カードイメージを構築しディレクトリを作成して MZF/バイナリアプリケーションをドライブイメージに追加します。 |
CP/M システムは 4 つの部分でビルドされます:
1. CCP、BDOS、CBIOS スタブを含む cpm22.bin。
2. プライマリソースが 4K ROM と 4 つのバンク化された 2K ROM にあるバンク化された CBIOS。
3. 任意の CP/M ドライブ文字に割り当てられる最大 2 つ(現在)の読み取り専用 CP/M ROM ドライブ。
4. バイナリを Rom Filing System に直接追加するのに適したセクター化 MZF イメージへの変換。
上記のすべては assemble_cpm.sh bash スクリプトにエンコードされており、以下のように実行できます:
cd <software>
tools/assemble_cpm.sh
CPM を使用するには、2×512KByte フラッシュ RAM にプログラミングできるモニター ROM と USERROM イメージを作成する必要があります:
cd <software>
tools/assemble_cpm.sh
tools/assemble_rfs.sh
tools/assemble_roms.sh
tools/make_cpmdisks.sh
tools/make_roms.sh
tools/make_sdcard.sh
ディスクフォーマット
わかったことですが、CP/M ディスクフォーマットは数百もあり、Sharp シリーズだけでもマシンごとに 2〜3 種類実装されています。この CP/M 実装に使用するフォーマットを決定するにあたり、既存のフォーマットを調べ、1.44MB、720K の 3.5” フロッピーの標準フォーマットと ROM ベースの 240K ROM ドライブを使用することにしました。
使用しているフォーマットは以下の diskdefs 定義を使用して cpmtools で操作できます:
diskdef MZ80A-A
seclen 256
tracks 40
sectrk 32
blocksize 2048
maxdir 64
skew 0
boottrk 1
os 2.2
end
diskdef MZ80A-1440
seclen 512
tracks 80
sectrk 36
blocksize 2048
maxdir 128
skew 0
boottrk 0
os 2.2
end
diskdef MZ80A-720
seclen 256
tracks 80
sectrk 36
blocksize 2048
maxdir 128
skew 0
boottrk 0
os 2.2
end
diskdef mz80a-rfs
seclen 128
tracks 15
sectrk 128
blocksize 1024
maxdir 32
skew 0
boottrk 0
os 2.2
end
diskdef MZ80A-SDC16M
seclen 512
tracks 1024
sectrk 32
blocksize 8192
maxdir 512
skew 0
boottrk 0
os 2.2
end
MZ80A CP/M ディスクの抽出
samdisk copy <MZ80A DISK NAME>.DSK <MZ80A DISK NAME>.RAW --cyls=40 --head=2 --sectors=16 --size=256
python3 -c "import sys; sys.stdout.buffer.write(bytes(~b & 0xFF for b in open('<MZ80A DISK NAME>.RAW','rb').read()))" > <MZ80A DISK NAME>_normal.RAW
cpmls -f MZ80A-A <MZ80A DISK NAME>_normal.RAW
cpmcp -f MZ80A-A <MZ80A DISK NAME>_normal.RAW 0:*.* /output/directory/
MZ80K CP/M ディスクの抽出
samdisk copy <MZ80K DISK NAME>.DSK <MZ80K DISK NAME>.RAW --cyls=40 --head=1 --sectors=18 --size=128
cpmls -f mz80k <MZ80K DISK NAME>.RAW
cpmcp -f mz80k <MZ80K DISK NAME>.RAW 0:*.* /output/directory/
MZ80B CP/M ディスクの抽出
samdisk copy <MZ80B DISK NAME>.DSK <MZ80B DISK NAME>.RAW --cyls=40 --head=2 --sectors=18 --size=256
python3 -c "import sys; sys.stdout.buffer.write(bytes(~b & 0xFF for b in open('<MZ80B DISK NAME>.RAW','rb').read()))" > <MZ80B DISK NAME>_normal.RAW
cpmls -f mz80b <MZ80B DISK NAME>_normal.RAW
cpmcp -f mz80b <MZ80B DISK NAME>_normal.RAW 0:*.* /output/directory/
MZ800 CP/M ディスクの抽出
samdisk copy <MZ800 DISK NAME>.DSK <MZ800 DISK NAME>.RAW --cyls=40 --head=2 --sectors=8 --size=256
mv <MZ800 DISK NAME>.RAW workingfile.raw
> total
dd if=workingfile.raw of=total count=8192 bs=1
for i in $(seq 8192 8192 327680); do
dd if=workingfile.raw of=blob skip=$i bs=1 count=4096
cat blob >> total
echo $i
done
for i in $(seq 12288 8192 327680); do
dd if=workingfile.raw of=blob skip=$i bs=1 count=4096
cat blob >> total
echo $i
done
mv total <MZ800 DISK NAME>.RAW
CP/M アーカイブ
CP/M アーカイブは Gitea から削除しました。必要な場合はzip ファイルをダウンロードしてリポジトリの <repo>/software ディレクトリに解凍してください。
cd <software>
tools/make_cpmdisks.sh
ディスクはディレクトリ <CPM>/1M44/DSK に作成されます。
このスクリプトはアーカイブの組み合わせを使用して 16MB SD カードドライブイメージもビルドします。