PC-8001 シリーズの中で唯一 mk2 だけが 1200baud でのカセット読み込み機能を有しています。ですが、折角の 1200bayd 読み込みは、N80-BASIC では使用されず封印されています。今回はその 1200baud を使って、様々なゲームを読み込ませる手法について解説します。


  • ファンクションキーを使った自動起動で 1200baud 読み込み
ファンクションキーを押下したフラグを立てると、自動的にキー入力が流れていきます。それを利用したのが $EA68 からの短いローダーでした。概ねこのような内容になっています。

org $EA68 db $01 ; キー入力ON REPT $EAC0 - $ nop ENDM db "l", $0D, "gc000", $0D, $00

$EA68 にフラグを立てて、$EAC0 から自動キー入力の流れを記述しています。この例では $C000 にジャンプしています。基本的にはモニタの L コマンドで読み込みますので、このままでは 600baud でしか読み込めません。ところで、$EAC0 と $EA68 の間には、88バイトの未使用空間があります。そこで、この空間に 1200baud で読み込めるプログラムを書き込みます。

org $EA68 db $01 ; キー入力ON ; 初期化 out ($5F), a ; 1200baud カセットからの読み込み xor a ld ($FF33), a ld a,($EA66) and %00000111 or %00011100 jp $5DC8 REPT $EAC0 - $ nop ENDM db "gea69", $0D, "ge000", $0D, $00

何をやってるのかと言えば、L コマンドの最初に読み込みの初期化を行っている箇所があるのですが、その前に自前でフラグ処理した値を Acc に入れたまま、ROM内ルーチンの途中にジャンプさせて L コマンドを発動させているのです。L での読み込みの代わりが、$EA69 から格納されていますので、そこにジャンプ先を変更しています。


  • 自前で 1200baud 読み込みをする
2段目の読み込みは自作のローダーからになると思います。その際に普通の書き方をすると、やはり 600baud でしか読み込めません。例えばこんなプログラムです。

.cmtopn call $0C3E ; CMT.MOTORON call $0BF3 ; CMT.ROPEN ; 読み込みアドレス設定 .start call $5F9E ; CMT.READ cp $3A ; CMT.GAP jr nz, .start ; Gapじゃなければ最初から .getadr call $5F9E ; CMT.READ ld h, a call $5F9E ; CMT.READ ld l, a ; HL Read address call $5F9E ; CMT.READ add a, h add a, l jp nz, .start ; チェックサム確認 ; ゲーム本体の読み込み .read call $5F9E ; CMT.READ cp $3A ; CMT.GAP jr nz, Error ; GAP以外ならエラー ; ブロックヘッダ call $5F9E ; CMT.READ or a ; 読み込み数が jr z, Launch ; ゼロなら起動させる ld b, a ; B 読み込み数 ld c, a ; C チェックサム ; データ .store call $5F9E ; CMT.READ ld (hl), a ; メモリに配置する inc hl ; HL 次のアドレスに add a, c ; チェックサム加算 ld c, a ; C チェックサム更新 djnz .store call $5F9E ; CMT.READ add a, c ; チェックサムを加算 jr z, .read ; 読み込みを継続する jr Error

mikilocos 虫虫ゲッター M-01
高芝ギムネ製作所(Takashiba Gimune)
※ これからの季節、虫を直接触れない虫嫌いなあなたの必携器具かと。私は毒がなければ普通に鷲掴みしますが😁
読み込み完了でLaunchに、エラー発生時は Error にジャンプします。このプログラムは、読み込みの初期化を ROM内ルーチン $0BF3 に依存しています。このルーチンは 600baud の読み込みしか想定していません。そのため、1200baud で読み込む場合はこれを使わず、初期化だけは自前で行います。初期化部分を掲載します。

.cmtopn call $0C3E ; CMT.MOTORON ld a, ($EA66) and %00000111 or %00011100 ; 1200baud設定 ld ($EA66), a out (PORT.CNTL1), a call $0C02 ; CMT.ROPENの途中から

やってることは殆どファンクションキーを使った場合と同じです。ハードの初期化部分を自前で行った後で、ROM 内ルーチン CMT.ROPEN の途中にジャンプしています。本来はルーチンの途中にジャンプはよろしくないのですが、PC-8001mk2 は生産が終わった製品ですので、アドレスが変更される可能性はゼロです。そのため、安心して途中にジャンプしていたりします。
※ このプログラムを実行すると、テキスト表示が壊れる場合があります。その場合は、DMA STOPとして見えなくするか、自前で CMT.MOTORON も用意する必要があります。


  • カセットからデータを読み込む際の注意点
私が10日近くもハマッた問題についても記載しておきます。カセット読み込みとは一見何の関係もなさそうな、割り込みコントローラ設定で間違ったフラグを立ててしまうと、カセットから正常に読み込めなくなります。具体的には…

; 割り込みテーブルを初期化する(カセット不具合あり Initialize: di ld a, Table.@H ld i, a ; Ireg をセット ld a, %00000111 ; 割り込みレベル参照 Lv.7 out ($E4), a ; INT0-7 入出力設定 ld a, %00000101 ; USART, Realtime 許可 out ($E6), a ; 割り込みマスク出力 ei ret

この初期化を行うと、カセット読み込みがおかしくなります。どこが悪いのかと言うと、$E6 に出力しているフラグです。%00000101 となっていますが、これを %00000001 とすると解決します。つまりは USART を許可してはイケないのです。このフラグを立てると、カセットコントローラはインタラクティブモードという、よくわからない動作モードに入ります。結果、カセットからのイベントで読み込みが発生して、そこを適切に処理しないと読めなくなってしまうのです。

ということで、正しいコードも上げておきます。2ms 割り込み部分はテーブル設定の後、確実に処理するようにしているのが前提のコードです。

; 割り込みテーブルを初期化する(正常動作 Initialize: di ld a, Table.@H ld i, a ; Ireg をセット ld a, %00000111 ; 割り込みレベル参照 Lv.7 out ($E4), a ; INT0-7 入出力設定 ld a, %00000001 ; Realtime のみ許可 out ($E6), a ; 割り込みマスク出力 ei ret
割り込み処理を使わないのであれば、

; 割り込み停止 Stop: di xor a ; 全て停止 out ($E6), a ; 割り込みマスク出力 ei ret
こうすれば発生しなくなります。割り込みに関しては、こちらでも解説していますのでよろしければご参照ください。


※ 自ら最強を名乗る蚊取り線香。蚊の季節到来です。コイツでヤられる前にヤる!