P6のキー入力についてまとめておきます。
1.キー入力は、全てサブCPUが管理している。
メインCPUからは、8255を通して通信を行ってデータを取得する事になります。
また、サブCPUとの通信は、通常は割り込みを使用します。
割り込みを使用しない方法も無くはないのですが、SR以降の挙動が変わるんじゃなかと思います。
以降、割り込みを使っているという前提で記載します。
2.キー入力の種類は4種類ある。
1)通常キー入力(割り込みベクタ0x02)
キー入力があった時点にサブCPUから割り込みが発生し、値を返してきます。
逆に、キー入力がないと、全く割り込みが発生しません。
そのため、キーが押下された事はわかりますが、キーを離した事はわかりません。
キーをずっと押下している場合は、サブCPU側でキーリピートの処理を行って、その都度割り込みが発生します。
キーリピートの間隔などの変更などもできず、何故か機種によって間隔も違うようです。
また、SHIFT/CTRL/GRPH/かな入力、ひらがな<->カタカナ切換(SHIFT+PAGE)もサブCPUの方で行っており、返ってくる値もそのコードになります。
ややこしいんですが、CAPSを押した時の処理はサブCPUで行っておらず、CAPSは普通の特殊キーの一つになっています。
2)特殊キー入力(割り込みベクタ0x14)
これに該当するキーは以下の通りです。右に返ってくる値を併記します。
グラフィックキー(GRPH+1〜9など):グラフィックコード(0x01〜0x1f)
ファンクションキー(F1〜F5):0xf0〜0xf4
SHIFT +F1〜F5 :0xf5〜0xf9
STOP :0xfa
CAPSキー :0xfb
SHIFT+PAGE :0xfc
MODEキー :0xfd
かなキー :0xfe
動作としては、1)通常キー入力と同じです。
押された時に、値を返してきて、ずっと押下している場合は、キーリピートされて、その都度割り込みが発生します。
3)ゲームキー入力(割り込みベクタ0x16)
1)2)とは違い、メインCPUからゲームキー調査のコマンドを発行します(サブCPUに対して0x06を出力)。
しばらくすると、サブCPUから割り込みが発生して、ゲームキーの状態を返してきます。
返ってくる値は以下の通り。
bit7-0:[SPC] ["L"] [←] [→] [↓] [↑] [STOP] [SHIFT] の押下状態(押している時"1"、離している時"0")
このゲームキー入力を使う事で、キーが押されているか、押されていないかがリアルタイムに分かります。
逆にここで検出できる SPACE/カーソル/STOP/SHIFT 以外は、リアルタイムで押下されているかどうかがわかりません。
4)CMT入出力時のSTOPキー入力(割り込みベクタ0x0e/0x10)
押された時点でサブCPUから割り込みが発生します。値は返してきません。
3.サブCPUとの通信について
BASICのROM内通信を使うのが一番手っ取り早いんですが、自前で全部作ると以下のようになります。
(下記は、拙作Meltdown for p6mk2から、一部抜き出して変更したもの)
;
; 割り込み関連
;
org $8400
INT_TABLE:
dw INTDT0 ; 0x00
dw INTKEYIN ; 0x02(通常キー入力)
dw INTDT0 ; 0x04(RS-232C)
dw INTTIMER ; 0x06(TIMER)
dw INTDT1 ; 0x08(CMT READ)
dw INTDT0 ; 0x0A
dw INTDT0 ; 0x0C
dw INTDT0 ; 0x0E(CMT使用時STOP入力)
dw INTDT0 ; 0x10(CMT使用時STOP入力)
dw INTDT0 ; 0x12(CMT ERROR)
dw INTKEYIN2 ; 0x14(特殊キー入力)
dw INTGAMEKEY ; 0x16(ゲームキー入力)
;
; サブCPUから1バイトデータを受信する
;
; RET:Areg=受信データ
;
GETSUBCPU:
ld a,$0c
out ($93),a
.wait:
in a,($92)
and $20
jr z,.wait
ld a,$0d
out ($93),a
in a,($90)
ret
;
; サブCPUへ1バイトデータを送信する
;
; Areg=送信データ
;
SETSUBCPU:
push af
ld a,$08
out ($93),a
.wait:
in a,($92)
and $80
jr z,.wait
ld a,$09
out ($93),a
pop af
out ($90),a
ret
;
; 割り込み終端(データ1バイト受信+何もしない)
;
INTDT1:
push af
call GETSUBCPU
pop af
;
; 割り込み終端(何もしない)
;
INTDT0:
ei
ret
;
; キー入力割り込み
; 通常キーは、ASCIIコード
;
INTKEYIN:
push af
call GETSUBCPU
ld (KEYDATA),a
pop af
ei
ret
;
; キー入力割り込み
; GRAPH+キーの場合は、そのASCIIコード
; ファンクションキーの場合は、0xf0〜0xf9
; STOPキーの場合は、0xfa
; CAPSキーの場合は、0xfb
; MODEキーの場合は、0xfd
;
INTKEYIN2:
push af
call GETSUBCPU
ld (KEYDATA2),a
pop af
ei
ret
;
; タイマ割り込み
;
INTTIMER:
push af
ld a,(TIMERCNT)
inc a
and $03
ld (TIMERCNT),a
jr nz,.next1
ld a,$06
call SETSUBCPU ; ゲームキー呼び出し
.next1:
pop hl←不要でした
pop af
ei
ret
;
; ゲームキー割り込み
;
INTGAMEKEY:
push af
push bc
call GETSUBCPU
;
; サブCPUからのゲームキーをJOYSTICKの並びに変更する
; SPC "0" 左右下上 STOP SFT
; ↓
; "0" STOP SFT SPC 右左下上
ld b,a
xor a
bit 2,b
jr z,.lp1
or $01
.lp1: bit 3,b
jr z,.lp2
or $02
.lp2: bit 5,b
jr z,.lp3
or $04
.lp3: bit 4,b
jr z,.lp4
or $08
.lp4: bit 7,b
jr z,.lp5
or $10
.lp5: bit 0,b
jr z,.lp6
or $20
.lp6: bit 1,b
jr z,.lp7
or $40
.lp7:
ld b,a
;
; ジョイスティックポートにアクセスする
;
ld a,$0f
out ($a0),a
ld a,$c0
out ($a1),a
ld a,$0e
out ($a0),a
in a,($a2)
cpl
and $3f
;
; Areg:"0" "0" TRG2 TRG1 右左下上
or b
ld (GAMEDATA),a
pop bc
pop af
ei
ret