PC-6001mkII/6601 CP/M導入メモ・その1

S-OS"SWORD"の移植が思いの外楽しかったので、次はCP/Mでもどうかなーと思い色々調べてみたのですが、既に昔のI/OでCP/MをPC-6001mkIIに移植した記事があるそうじゃありませんか。先達に感謝。PC-6601/SRでも動くか確認してみたところ、基本的にそのまま動くようです。その作業記録をまとめてみました。

まあ今更CP/Mかという話ではあるのですが、今だからこそ導入が楽になった部分もあります。CP/Mの構造は、BIOSと呼ばれる機種依存部分と、各機種で共通に使われるシステム部分であるBDOS(システムコールルーチン)及びCCP(コマンドラインプログラム)から成っており、BIOS部分を変更すればそれ以外は共通のバイナリがそのまま動きます。そのためI/Oの移植記事では、新たに書かれたBIOSのダンプリストを掲載し、共通部分はPC-8801用のCP/Mから転送するようになっていました。これはけっこう高いハードルで、記事の通り移植するには6001mkIIとFDDに加え、RS-232Cユニット、PC-8801と8インチFDD、そして88用に市販されているCP/Mが必要だったわけです。

しかし、現在CP/Mの共通部分はThe Unofficial CP/M Web siteより自由にダウンロードできるようになっており、起動ディスクイメージ作成までを現代のPC上で行うことができます。また、多くのCP/Mアプリケーションもやはりネット上で公開されており、利用するのに必要な条件は昔に比べると随分少なくなったと言えるでしょう。ここでは、そのあたりの手順について書き留めておこうと思います。BIOS部分はI/Oのリストを入力する必要がありますし、共通部分も再配布は許可されていないようなのであくまで手順の紹介のみとなりますが、何かの参考になれば幸いです。

(※2012.8.7追記:BIOSを自作してみました。導入メモその2をご覧ください。)

CP/Mの画像
PC-6601でCP/M


目次


必要なもの

最大のハードルとして、当時のI/Oを入手してリストを入力する必要があります。ただ、I/Oはパソコン雑誌の中では図書館に置いてある確率が高い方らしく、都道府県立などの大きめの図書館にはわりと所蔵されているようです。最近はネットで所蔵図書を調べられるところも多いので、近くの図書館にあるか確認してみてください。近くに無い場合は、図書館間での相互貸し出しや、国会図書館の遠隔複写サービス(要登録)を利用するといいでしょう。自分の場合は、神奈川県立川崎図書館というところで閲覧及び複写することができました。

CP/Mを動かすのに必要な記事は以下の通りです。

一つめがCP/Mの移植記事で、二つめは80×25の画面を仮想的に実現する拡張用プログラムです。スクリーン指向のアプリケーションを動かす場合は、端末制御用のコントロールコードやエスケープシーケンスを使用するため、後者も必要になります。


CP/Mのアセンブル

まずはCP/Mの共通部分、BDOSとCCPのイメージファイルを用意しましょう。I/Oの記事ではPC-8801のCP/M上でイメージを作ることになっています。公開されているCP/MバイナリとCP/Mエミュレータを使って同様のやり方でイメージファイルを作ることもできるのですが、ここではソースをアセンブルする方法について紹介します。

アセンブラとしては、MS-DOS用のZ80アセンブラZASMを使いました。64ビットWindowsではMS-DOS PlayerDOSBox、LinuxではDOSEMUといったDOSエミュレーション環境を使えばZASMが動くようです。また、他のアセンブラを使っても手順にさほど大きな違いは無いと思います。

  1. The Unofficial CP/M Web siteのDigital Research Source Codeより、「CP/M 2.2 ASM SOURCE」をダウンロードして展開します。ファイル名はcpm2-asm.zipです。
  2. 展開ファイル中の「CPM22.Z80」を使います。以下の変更を加えてください。
    1. 14行目の「MEM EQU 62」を「MEM EQU 49」に変更します。
    2. 2043行目の「ADD A,M」を「ADD A,(HL)」に変更します。
    3. 2168行目、3340行目、3343行目の「SBC A,M」を「SBC A,(HL)」に変更します。
    4. 367行目、674行目のラベル「HALT」を「_HALT」に変更します。
    5. 1284行目の「NFUNCTS EQU 41」を、1267行目の「CP NFUNCTS」より前に移動します。
    6. ファイルの最後に「END」と書いた行を追加します。

    「MEM」は機種により異なるCP/Mのメモリサイズです。I/O掲載のP6用CP/Mでは49Kになっているので、49にします。また、8080のニモニックである「... A,M」という表記が混じっているので、Z80のニモニックである「... A,(HL)」に修正します。最後の三つはアセンブラの文法用の修正です。ZASM以外を使う場合はもしかしたら必要ないかもしれません。

  3. アセンブルします。コマンドプロンプトで、
    zasm -z -ccpm.bin cpm22.z80
    とすると、バイナリイメージcpm.binが作成されます。正しくアセンブルされればサイズは5683バイトになります。

(2012.8.12追記:うまくアセンブルできないという質問のメールをいただきました。ZASMではラベル定義文は行頭から始まらないといけないようなので、「NFUNCTS EQU 41」の頭にはタブやスペースを入れないようにしてください。)


ディスクイメージの作成

続いて、I/O84年2月号掲載のプログラムを入力します。記事通りP6上で入力してもいいのですが、ここでは現代のPC上でバイナリエディタを使って入力し、前項のCP/Mイメージと合わせてディスクイメージを作るところまでやってしまうことにします。

  1. リスト3を打ち込み、boot.binというファイル名で保存します。
  2. リスト4を打ち込み、bios.binというファイル名で保存します。

    印刷が薄い部分が多く非常に見づらいので、チェックサムの確認は必須です。むしろ読めない部分を解読するためにチェックサムが必要でした。チェックサム計算プログラム (ソースWindows用実行ファイル) を置いておきます。(コンソール用プログラムです)

  3. cpm.bin、boot.bin、bios.binの三つが揃ったら、ディスクイメージ作成プログラム (ソースWindows用実行ファイル) を実行します。(コンソール用プログラムです)
    (※2012.8.29追記:しばらく前から間違ったプログラムに置き換わっていたようです。差し替えました。もし試された方がいましたらすみません。)

    I/O掲載のリスト1、2を使った場合と同等のD88イメージファイルを自動的に生成するプログラムです。正常に終了すると、cpm.d88という174768バイトのファイルができます。

    (※もちろんリスト1、2を使っても構いません。ただ、PC-6601ではリスト1のフォーマットプログラムは動かないようです。動かない部分は恐らく物理フォーマットではないかと思うので、40トラック1Dとして物理フォーマットしたディスクを用意し、160〜220行目の論理フォーマットを施せば同等の結果が得られると思います。)

以上でCP/MのシステムディスクのD88イメージが完成です。cpm.d88をNDitt等でディスクに書き込めば、実機でCP/Mが起動します。


アプリケーション導入例 〜Zork I編〜

Zork Iの画像
PC-6601でZork I

試しにCP/Mアプリケーションを動かしてみましょう。まずはやっぱりゲームだよねーということで、テキストアドベンチャーの古典的名作、Zorkを遊んでみることにします。Zorkは三部作ともRetrocomputing Archive等のサイトでダウンロードできます。

  1. Retrocomputing Archiveで、zork123_80.zipをダウンロードして展開します。

    三部作それぞれの実行ファイルとデータファイルがあります。とりあえず第一作の分、ZORK1.COMとZORK1.DATをディスクにコピーしてやることにしましょう。コピーのやり方は色々あると思いますが、ここではエミュレータを使う方法を紹介します。使用したのはPC6001VW ver 307a2です。

    (追記:導入メモその2では、cpmadd.exeというファイル追記コマンドを用意しました。これを使うと、コマンドラインからcpmadd cpm.d88 zork1.* zork1.d88 とするだけでディスクイメージが作成できます)

  2. ZORK1.COMとZORK1.DATをエミュレータのdevフォルダに置きます。以下ファイルのコピーはすべてこのdevフォルダを介して行います。(ファイル名の頭に展開フォルダ名を付けてもいいです)
  3. PC6001VWを立ち上げ、前項で作ったディスクイメージでCP/Mを起動します。
  4. エミュレータのモニタモードでファイルをメモリに読み込んで、CP/Mコマンドでディスクに書き込みます。Alt+F6キーでモニタモードです。以下P6VW>というプロンプトはモニタモードを、a>というプロンプトはCP/M上の操作を示します。

    P6VW>loadmem zork1.com 0x100
    P6VW>g
    a>save 34 zork1.com

    CP/Mのユーザエリア先頭番地である0x100をロードアドレスとして指定します。saveはCP/Mの内蔵コマンドで、引数はファイルサイズとファイルネームです。ファイルサイズについては、256バイトサイズの「ページ」という単位での指定になります。ZORK1.COMのサイズは8704バイトなので、8704/256=34ページですね。

  5. 続いてデータファイルZORK1.DATですが、ファイルサイズが84992バイトもあるのでメモリに入りません。一旦ファイルを分割する必要があります。二分割すれば42496バイトずつでユーザエリアに入りそうです。256で割り切れる数字なのも確認しておきます。ただ、Windowsではファイルの分割を行う標準的な方法はどうも無いらしく、圧縮ソフトのファイル分割機能等を使う必要があるようです。自分はcygwinのddコマンドを使いました。それぞれ1.datと2.datという名前にしておきます。
  6. 分割したファイルをメモリに読み込んでディスクに書き込みます。

    P6VW>loadmem 1.dat 0x100
    P6VW>g
    a>save 166 1.dat
    P6VW>loadmem 2.dat 0x100
    P6VW>g
    a>save 166 2.dat

    続いて、CP/M上で二つのファイルを結合します。結合は、CP/M内蔵コマンドではなく、PIPという外部コマンドを使用して行います。

  7. CP/M 2.2 BINARYをダウンロードします。ファイル名はcpm22-b.zipです。
  8. 展開し、PIP.COMをディスクに書き込みます。

    P6VW>loadmem pip.com 0x100
    P6VW>g
    a>save 29 pip.com

  9. (設定が1ドライブならば) 2ドライブ設定にしてPC6001VWを立ち上げ直します。

    1Dディスクのサイズは、40トラック使っても160Kバイトなので、結合前と結合後のファイル両方は入りきりません。よってBドライブを使います。実機で2ドライブ構成を用意するのは今や困難ですが、エミュレータなら簡単ですね。素晴らしい。

  10. D88ファイルをコピーして両方のドライブにセットします。
  11. ファイル結合を行います。

    a>era 1.dat
    a>era 2.dat
    a>pip zork1.dat=b:1.dat[o],b:2.dat[o]

    Aドライブの方のファイルをERAコマンドで削除してスペースを空け、Bドライブのファイルを結合して書き込みました。「PIP 新ファイル=元ファイル」という文法ですね。ファイル名の後ろに付いている[o]はObjectの略で、バイナリファイルの意味です。これが無いとテキストファイルと見なされ、ファイル終端記号であるCtrl-Zがあるとそこでコピーが打ち切られてしまいます。

  12. 結合が済んだら、zork1と打ち込めばゲーム開始です。

ちなみに、手元の環境ではエミュレータ上だとキー入力の反応が非常に鈍くなるケースがあります。マシンパワーのせいでしょうか? (実機では問題無し)


アプリケーション導入例 〜Rogue編〜

Rogueの画像
PC-6601でRogue。Kは大隼じゃないのね

ゲームばかりで何ですが、次はRogueを試してみます。言わずと知れたローグライクゲームの始祖ですね。Zorkと同様、PC6001VWを使ってディスクへのコピーを行いました。

  1. The Roguelike Archiveからrogue17cpm.zipをダウンロードして展開し、その中のrogue17.zipを更に展開します。その中にあるROGUE.CPMがCP/M用実行ファイルです。
  2. エミュレータに読み込んでディスクに書き出します。セーブ時のファイル名はROGUE.COMとします。

    P6VW>loadmem rogue.cpm 0x100
    P6VW>g
    a>save 89 rogue.com

  3. Rogueは80×25画面用のゲームなので、I/O85年6月号の80桁仮想スクリーンプログラムを使う必要があります。チェックサム無しという非常に凶悪なリストですが、頑張って入力してください。Rogueを遊ぶ分にはリスト1〜3のみでOKです。参考になるかわかりませんが、自分が打ち込んだリストの16バイトごとの横単純サムを載せておきます。(※正しい保証は全くありません!)
    リスト1 "HELLO"
    60 5F DA 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 57 3D 00 00 00 00 00 00 00 00 00 00 00 00
    D1 7A E9 97 63 8B 08 C8 A0 1B 08 AE ED F8 7E C2
    E3 19 C5 8D BA 35 DE 3E FA B3 16 B9 D9 DF E9 EE
    8D 4A 48 47 A9 CA FE 43 93 FE 79 10 5C 9D BB 30
    11 C4 F8 7B CA 02 FC E3 81 EF EC 4C 5D 1C BD 96
    0E 2D 98 B5 D1 82 EB 9A 6B 1B 86 C0 A6 B1 E9 E0
    3C E4 30 70 2F 7E 85 A6 C1 75 A5 C6 0B 4B FB C8
    0F 27 25 4C 35 B4 11 70 C1 E6 F4 10 DC 00 00 B0
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 01 A0 0C 39 E6 42 ED 27 CA 65 00 00 00 00
    
    リスト2 "CONNVD"
    6C F4 F0 92 58 50 B6 3F E7 5B 86 16 F2 9E 6A D7
    
    リスト3 "KILLVD"
    6C 79 59 92 58 50 B6 3F E7 5B 86 16 F2 9E 6A D7
    
    リスト4 "WSPARIN"
    B2 00 65 19 64 00 00 00 00 00 00 00 00 00 00 00
    B2 DD 6A 24 89 90 90 90 90 90 90 90 87 F8 50 90
    B3 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    
    リスト5 "FKS"
    34 E8 24 11 CA 06 9B A4 94 AF 9E DF F4 A5 62 AD
    
  4. Rogueを正常に動作させるためには、HELLOを一部変更する必要がありました。アドレス0605〜0606の「A8 DA」を、「B1 DB」に変更してください。コントロールコード0x1Aによる画面クリア時に、カーソル位置が原点にリセットされるようになる変更です。他のアプリケーションでは変更を戻さないと駄目な場合があるかもしれません。
  5. それぞれディスクに書き込みます。

    P6VW>loadmem hello.bin 0x100
    P6VW>g
    a>save 18 hello.com
    P6VW>loadmem connvd.bin 0x100
    P6VW>g
    a>save 1 connvd.com
    P6VW>loadmem killvd.bin 0x100
    P6VW>g
    a>save 1 killvd.com

  6. 以下のように入力するとRogueが起動します。F1で画面上部切り替え、F2で画面下部切り替えです。

    a>hello
    a>connvd
    a>rogue

これも実機だと正常ですがエミュレータによってはキー入力が鈍かったり落ちたりします。なんでだろう?


トップ > 雑多なもの > PC-6001mkII/6601 CP/M導入メモ・その1