NEC PC-8001 の後継機である PC-8001mkⅡは、追加機能が中途半端だった事もあり、また、ほぼ同時期に発売された PC-8801 がゲームのメインストリームに変わった事も手伝って、当時からかなり不遇の存在でした。ですが、色数が少ないとは言え、DMA を止めれば無印80より2倍ぐらい CPU処理速度は上がりますし、グラフィックRAMの容量が小さい事で、画面書き換えも比較的高速と、意外とバランスの取れた名器であったりもします。今でもファンが多いのも納得です。

その 80mk2 の隠れた特徴として、リアルタイム割り込みを発生させられるという特徴があります。この割り込みを使えば、ゲームの実行速度を固定化させる事も容易ですし、またサウンド再生のテンポを一定にして安定した音楽再生も可能だったりします。ただ、本体だけではBEEPしか鳴らないのが玉に瑕なのですが、HAL研究所から発売されていたPCG8200を搭載すれば、3和音で音楽再生が出来ますので、一気に魅力が上がったりします。※ DMA 止めたら PCG 見えなくなりますが…

今回はこの80mk2の割り込みの使い方について解説してみたいと思います。


  • 初期化
割り込みは二つのポートで制御できます。$E4が割り込みレベルの設定です。$E6がどの割り込みを発生させるかという割り込み制御フラグの設定となります。割り込みに関しては、想像ですが CMT I/F も使用している可能性があります。※ 読み込み完了後は止めても良いとは思いますが…

割り込みレベルは低いと発生しないようで、私のテスト実装では設定できる最大の 7 を指定しました。あと、割り込みテーブルアドレスは I レジスタを参照しているようで、こちらにテーブルの上位 8bit データを格納します。そして、これが一番大事なのですが、I レジスタに格納したアドレス + 4 に、リアルタイム割り込みがかかった際に、実行されるエントリアドレスを格納する必要があります。

これらの設定を Z80 で記述すると以下のようになります。

INTTBL equ $D000 ; 割り込みテーブルアドレス ; 割り込みの初期化 di ld a, INTTBL.@H ld i, a ; Ireg を INTTBL の上位にセット ld a, %00000111 ; 割り込みレベル参照 Lv.7 out ($E4), a ; INT0-7 入出力設定 ld a, %00000001 ; Realtime 許可 out ($E6), a ; 割り込みマスク出力 ld hl, INTEntry ; 割り込みエントリアドレス ld (INTTBL + 4), hl ; 割り込みテーブルに設定 ei

アセンブラは AILZ80ASMを使用しました。このアセンブラは、.@H マクロで上位アドレスを 8bit データとして取得できます。普通のアセンブラであれば、ここは…

ld a, INTTBL / 256

このように記述してください。この例だとは $D004, $D005 はジャンプ先アドレスが格納されますので、そちらにプログラムコードやワークエリアは設定できないです。ご注意ください。
※ Bluetooth でスマホと接続、時間調整とか、夜間秒針停止とか超高機能!

  • 割り込み処理
割り込みがかかると、INTTBL + 4 に書かれたアドレスに、実行が移ります。2ms(本当にこんな速度で来ているかどうかは未検証ですが)で飛んでくるので、あまり重い処理を行うのは御法度です。必要に応じてさっさと割り込みを終了させてください。

割り込みは、どこかで実行されている状態を中断で飛んできますので、レジスタ内容はおろか、フラグに至るまで、現在の状態を保存する必要があります。そのため、通常は、割り込み処理内で使用しているレジスタはスタックに保存します。

余談ですが、本来は割り込みのために EXX, EX AF,AF' といった裏レジスタが存在しています。なので、それぞれの処理で裏レジスタを使わない前提と出来るのであれば、サクッと裏レジスタに切り替えるだけで良かったのですが、Z80 のレジスタの足りなさと言ったら辛みばかりなので、裏レジスタも使っちゃいますよね…

ということでサンプルでは、画面左上のキャラクター文字を変化させるだけとしています。

; 割り込み処理 INTEntry:: di push af ; [AF push hl ; [[HL ld hl, $F300 inc (hl) ; 画面に変化を ld a, $FF ; 割り込み処理終了を out ($E4), a ; コントローラに通知 pop hl ; ]]HL pop af ; ]AF ei ret

割り込み処理内では、AF,HL しか使いませんでしたので、それだけスタックに待避しています。割り込みの終了は RET で指定してください。reti は遅いだけで意味がありませんでした。

割り込み処理の終了時に割り込みレベルに $FF を設定しています。どうやらもう一度割り込みを発生させるために必要のようです。


  • 割り込みを止める
一度割り込みを発生させたら、ゲーム中にテープロードをする事が無ければ、そうそう割り込みを止める必要はない気もしますが、とりあえず止め方も。これはとても簡単で、割り込み制御フラグの全ての bit を消すだけです。

; 割り込み停止 INTStop:: di
xor a out ($E6), a ; 割り込みマスク出力 ei ret
と言う事で最後にサンプルです。

80mk2INTTest-3.zip
2024.05.21

このサンプルは本記事内で説明した内容のままとなっています。PC-8001mk2 の動作するエミュ、または実機でと動作します。

20240521-2130追記
この記事で USART の bit を 1 にしていましたが、これは RS232C とカセット関連の制御用でした。そして、意味もなくフラグを 1 にすると、カセットテープ読み込みに支障をきたすことがわかりました。そのため、本記事内のコードとサンプルを変更しています。間違った情報掲載でご迷惑をおかけいたしました。よろしくお願いいたします。
パール金属 真空 断熱 ジョッキ 450ml ステンレス H-6054
パール金属(PEARL METAL)
2013-02-01
※ 暑い夏にはキンキンに冷えたビール!パール金属のステン真空ジョッキならキンキン冷え冷えが長続きします!