プレイヤーが過ってCOPYキーを押すと、白帯が出てゲームプログラムが止まってしまうというのは問題です。
また、本体のINTERRUPTスイッチについても、故意に押される可能性があります。
コマンドプロンプト画面ならまだいいのですが、ゲームに使う縦256ドット解像度画面で白帯が出ると見苦しいので、 初期化処理の一環として対策します。
COPYキーが押されると、X68000の規定ではtrap #12の例外が発生します。
「trap」とか「例外」とか知らない用語に身構えたかもしれませんが、 実は既に使っているIOCSコールはtrap #15の例外です。
余談ですがついでに言うと、trap #11はSTOPキー、 trap #10は電源スイッチやソフトウェアリセットなどを捕捉します。
話を戻しますが、COPYキーが押されたときに白帯が出てしまうのは、trap #12の例外処理で、 プリンタ接続を確認しようとして応答がないときです。そこで、例外処理そのものを無害な処理に 置き換えるという方針で対策できます。
【COPYキー無効化処理】
_INTVCS equ $ff25 pea COPY_rte(pc) move #32+12,-(sp) * trap 12 COPY key DOS _INTVCS addq.l #6,sp lea vctCOPY(pc),a0 move.l d0,(a0) : COPY_rte: rte vctCOPY: .dc.l 0
DOSコール INTVCSは、ベクタと言う、例外処理の飛び先テーブルを書き換えるシステムコールです。
このプログラムでは、COPY_rteに書いてある、rte命令だけの処理に飛ぶようにしています。
rteは、例外処理を終える命令です。サブルーチンから帰るときのrtsと混同しないように注意してください。
DOSコールの戻り値は、書き換え前の飛び先アドレス(通常のCOPYキー動作)です。復元するときに必要なので、vctCOPYに保存し、以下のように使います。
【COPYキー復元処理】
move.l vctCOPY(pc),-(sp) move #32+12,-(sp) * trap 12 COPY key DOS _INTVCS addq.l #6,sp
Interruptスイッチについて方法は同じで、NMIという例外処理を、規定の白帯処理から 無害な処理に置き換えます。
【Interruptスイッチ処理】
* 無効化 * pea NMI_rte(pc) move #31,-(sp) * NMI DOS _INTVCS addq.l #6,sp lea vctNMI(pc),a0 move.l d0,(a0) * 復元 * move.l vctNMI(pc),-(sp) move #31,-(sp) * NMI DOS _INTVCS addq.l #6,sp NMI_rte: move.b #4,$e8e007 * NMI clear rte vctNMI: .dc.l 0
Interruptキーの処理に限って、システムポート$e8e007に4を書きます。 これは、INTERRUPTスイッチの検出をリセットする規定の手続きです。
とりあえずCOPYキーとInterruptスイッチを黙らせることはできました。 でも、せっかくなら何か意味のある使い方をしたいものです。
そこで、COPYキーの処理をひと工夫してみます。
COPY_rte: btst.b #0,$80e * SHIFT key beq @f bsr QUIT @@: rte quit_flag: .dc.w 0 QUIT: move.l a0,-(sp) lea quit_flag(pc),a0 move #-1,(a0) movea.l (sp)+,a0 rts
quit_flagという、初期値0のフラグ変数を確保しました。
QUITというサブルーチンも定義し、プログラムのどこからでも、 bsr QUITと呼び出せば、quit_flagが-1に書き換えられるようにします。
そして、COPYキーが押されたときの処理については、 SHIFTキーと一緒に押された場合に、QUITサブルーチンを呼ぶようにします。
$80eは、IOCSのワークエリアで、キーボードのキーの押し下げ状態を 保持しているところを覗き見ています。BITSNSというIOCSコールに関連する場所です。
これによって、「SHIFTキーを押しながらCOPYキーを押すと、quit_flagがセットされる」 という動作になります。
quit_flagを何に使うかは、このあとのお楽しみにしておきましょう。
Copyright©2026 カピバラ父さん