PC-9801のキーボード
PC-9801のキーボードは、FM-7と違ってキーボードコントローラーのI/Oに直接アクセスする事によって、現在キーが押し下げられているか離されているかをチェックする事ができます。それが、PC-9801が一時期ゲームマシンとして大流行した理由の1つでもあります。
MS-DOS割り込み INT21H
キー入力ルーチンを作る場合、大抵はMS-DOSのINT 21Hで十分ですし、できる限りこちらを使うべきです。
キーボードから1文字入力
AHレジスタ |
エコーバック |
[Ctrl][C]チェック |
01H |
あり |
あり |
06H |
あり |
なし |
07H |
なし |
なし |
08H |
なし |
あり |
キーボードから1文字入力します。入力があるまで待ちます。出力は、いずれもALに文字コードが入ります。
キーバッファの検査
入力 |
出力 |
AH=0BH |
AL
00H キーバッファにデーターなし
FFH キーバッファにデーターあり |
AH=01H,06H,07H,08Hはいずれもキーボードから入力があるまで待ちます。キーが押されるまで待ちたくない場合は、このAH=0BHでキーバッファをチェックして、キーバッファにデーターがある事を確認してから、AH=01H,06H,07H,08Hを使います。
キーバッファをクリアしてから1文字入力
AHレジスタ |
ALレジスタ |
エコーバック |
[Ctrl][C]チェック |
0CH |
01H |
あり |
あり |
06H |
あり |
なし |
07H |
なし |
なし |
08H |
なし |
あり |
いったんキーバッファをクリアしてから1文字入力を求めます。そのため、キー入力があるまで必ず待ちます。重要なメッセージを表示させる場合、その前にキーボードを連打していたら読む前にメッセージが先に進んでしまうと困るので、このファンクションでキーバッファをクリアしてからキー入力待ちをさせましょう。
キーボードBIOS INT18H
大抵はMS-DOS割り込みだけで十分なのですが、それだけだとPFキーの判別ができない、シフトキーの状態を読めない、キーが押し下げられているか離されているかがわからない、といった問題があります。
え?PFキーって何かって?これは「プログラマブル・ファンクションキー」の略です。だって、「Fキー」って表記したら単なる[F]のキーみたいじゃん?というわけで、このサイトで「PFキー」という表記が出てきたら、[F1]〜[F10]の事だと思ってください。
MS-DOS割り込みは汎用性を重視するため、シフトキーやPFキーの状態の取得までは対応していません。そこで、PFキー、シフトキーの状態を読み取る場合には、キーボードBIOSを利用します。
AH=00 キーボードから1文字入力
入力 |
出力 |
AH=00H |
AH キーコード
AL キーデータ |
キーボードから1文字入力し、入力があるまで待ちます。エコーバックはされません。このファンクションを使うと、MS-DOS割り込みではできなかったキーコードを取得する事ができます。なので、フルキーとテンキーの区別やPFキーの判別ができます。
AHレジスターに返るキーコードは以下の通りです。16進数です。
キー |
キーコード |
キー |
キーコード |
キー |
キーコード |
フルキー1 |
01 |
テンキー0 |
4E |
A |
1D |
フルキー2 |
02 |
テンキー1 |
4A |
B |
2D |
フルキー3 |
03 |
テンキー2 |
4B |
C |
2B |
フルキー4 |
04 |
テンキー3 |
4C |
D |
1F |
フルキー5 |
05 |
テンキー4 |
46 |
E |
12 |
フルキー6 |
06 |
テンキー5 |
47 |
F |
20 |
フルキー7 |
07 |
テンキー6 |
48 |
G |
21 |
フルキー8 |
08 |
テンキー7 |
42 |
H |
22 |
フルキー9 |
09 |
テンキー8 |
43 |
I |
17 |
フルキー0 |
0A |
テンキー9 |
44 |
J |
23 |
= - ほ |
0B |
テンキー/ |
41 |
K |
24 |
~ ^ へ |
0C |
テンキー* |
45 |
L |
25 |
| \_ |
0D |
テンキー- |
40 |
M |
2F |
Back Space |
0E |
テンキー+ |
49 |
N |
2E |
TAB |
0F |
テンキーEnter |
1C |
O |
18 |
ESC |
00 |
|
|
P |
19 |
Enter |
1C |
|
|
Q |
10 |
HELP |
3F |
|
|
R |
13 |
HomeCLR |
3E |
|
|
S |
1E |
XFER |
35 |
|
|
T |
14 |
Ctrl XFER |
B5 |
|
|
U |
16 |
NFER |
51 |
|
|
V |
2C |
Ctrl NFER |
B1 |
|
|
W |
11 |
VF1 |
52 |
|
|
X |
2A |
VF2 |
53 |
|
|
Y |
15 |
VF3 |
54 |
|
|
Z |
29 |
VF4 |
55 |
|
|
< , ね |
30 |
VF5 |
56 |
|
|
> . る |
31 |
F1 |
62 |
|
|
? / め |
32 |
F2 |
63 |
|
|
_ \ ろ |
FF |
F3 |
64 |
|
|
|
|
F4 |
65 |
|
|
|
|
F5 |
66 |
|
|
|
|
F6 |
67 |
|
|
|
|
F7 |
68 |
|
|
|
|
F8 |
69 |
|
|
|
|
F9 |
6A |
|
|
|
|
F10 |
6B |
|
|
|
|
資料がなかったので、自前のプログラムを作って1つ1つ押してみて調べました。確認ミスで違ってる場合もあります。違ってたら掲示板かツイッターで教えてください。
ALレジスターにはキーデーター、要するに押した時に出力されるアスキーコードが入ります。Aなら41H、aなら61Hですね。キーデーターは同じキーを押してもシフトキーやCAPSロック、カナロックの状態により変化します。PFキーやVFキーにはキーデーターはないので00Hが返ります。
PFキーの1〜10が押されるまで待つためには、キーコードに62H〜6BHが返るまでキー入力を待てば良いわけです。例えば、F1〜F10が押された場合は、AXレジスタに1〜10、それ以外は0が返るとして・・・
YOMI = $
MOV AH,0
INT 18H
CMP AH,62H
JAE $+5
JMP YOMI2
CMP AH,6BH
JBE $+5
JMP YOMI2
MOV AL,AH
MOV AH,0
SUB AL,61H
JMP YOMI3
YOMI2 = $
MOV AX,0
YOMI3 = $
:
(省略)
:
よく「レジスタに0を入れる時は自分自身とXORを取らないとダメだろ」って言われるんですけど、一応私個人としては0を入れるという事が見てわかりやすくするために、あえて0をMOVで入れてます。それに、自分自身とXORしないで0をMOVする事で体感的に遅いと感じた事もないし。
AH=01 キーバッファのチェック
入力 |
出力 |
AH=01H |
AH キーコード
AL キーデータ
BH 0バッファにデーターなし
1バッファにデーターあり |
キーバッファをチェックして、キーバッファにデーターがあればBHレジスタに1を返します。キー入力があるまで待ちません。キーバッファにデーターがある場合は、キーバッファの先頭のキーコードとキーデータを返しますが、キーバッファはそのままになります。したがって、キーバッファにデーターがあればキーバッファから1つ取り出したい場合は、キーバッファをチェックしてBHレジスタが1ならAH=00Hのファンクションをもう一度呼ぶ必要があります。
これを利用して、キーバッファをクリアする事ができます。
;-----------------------------------------------------------------------------
; キーバッファ初期化
;-----------------------------------------------------------------------------
BUFFC = $
MOV CX,100
BUFFC1 = $
MOV AH,1
INT 18H
CMP BH,1
JE $+5
JMP OWARI
MOV AH,0
INT 18H
LOOP BUFFC1
JMP OWARI
ここでOWARIは、PUSHしていたレジスタをPOPしてMS-DOSに戻るルーチンなので、あまり気にしないでください。
キーバッファのクリアを100回で強制的に終わらせている理由は、ユーザーがキーボードを押しっぱなしにしていたり、キーボードに物が乗っている場合に無限ループになってしまうからです。その場合は、画面に「11111111111111…」と延々に表示されてユーザーが「あ、やべっ」と自分で気がついた方がいいので、あえて有限ループになっています。
AH=02H シフトキーの状態のチェック
AL シフトキーの状態
ビット |
意味 |
4 |
0 Ctrl キーが押されてない 1 Ctrl キーが押されてる |
3 |
0 GRAPHキーが押されてない 1 GRAPHキーが押されてる |
2 |
0 カナロックされてない 1 カナロックされてる |
1 |
0 CAPS LOCKされてない 1 CAPS LOCKされてる |
0 |
0 シフトキーが押されてない
1 シフトキーが押されてる |
シフトキー、Ctrlキー、GRAPHキー、CAPS LOCKの状態、カナロックの状態は、AH=00ではわかりません。これらのキーはキーバッファにたまらないので、キーバッファをチェックしてもわかりません。そこで、このファンクションで押下状態をチェックします。
どのキーが押し下げられているかのチェック
AH=04H キーの押下状態のチェック
入力 |
出力 |
AH=04H AL キーコードのグループ番号 |
AH グループ内の8つのキー押下状態 |
このファンクションを使う事で、キーが押し下げられているか放されているかチェックする事ができます。FM-7みたいにテンキーを押すと5キーで固定するまでずっとその方向に動きっぱなしなんて事になりません。
どのキーがどのグループで、どのビットが立つのか手持ちの資料に掲載されていませんでしたので、こちらでテストプログラムを作って調べましたが、T98-Nextでは対応していないキーは調べることができませんでした。
グループ |
ビット |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
00H |
フルキー7 |
フルキー6 |
フルキー5 |
フルキー4 |
フルキー3 |
フルキー2 |
フルキー1 |
ESC |
01H |
TAB |
Back Space |
フルキー \ |
フルキー ^ |
フルキー - |
フルキー0 |
フルキー9 |
フルキー8 |
02H |
I |
U |
Y |
T |
R |
E |
W |
Q |
03H |
D |
S |
A |
Enter |
[ |
@ |
P |
O |
04H |
: * け |
; + れ |
L |
K |
J |
H |
G |
F |
05H |
M |
N |
B |
V |
C |
X |
Z |
] |
06H |
ROLLDOWN |
ROLLUP |
XFER |
SPACE |
\ _ ろ |
/ ? め |
. > る |
, < ね |
07H |
HELP |
HOME CLR |
↓ |
→ |
← |
↑ |
DEL |
INS |
08H |
テンキー5 |
テンキー4 |
テンキー * |
テンキー9 |
テンキー8 |
テンキー7 |
テンキー / |
テンキー - |
09H |
テンキー, |
テンキー0 |
テンキー = |
テンキー3 |
テンキー2 |
テンキー1 |
テンキー + |
テンキー6 |
0AH |
|
VF5 |
VF4 |
VF3 |
VF2 |
VF1 |
NFER |
テンキー . |
0BH |
|
|
|
|
|
|
|
|
0CH |
|
F5 |
F4 |
F3 |
F2 |
F1 |
COPY |
|
0DH |
|
|
|
|
F10 |
F9 |
F8 |
F7 |
0EH |
|
|
カナ |
CTRL |
GRAPH |
|
CAPS |
SHIFT |
※注
・Enterはフルキーとテンキーともに同じみたいです。
・ROLLUPはエミュレーターではPageDown、ROLLDOWNはエミュレーターではPageUPです。
・STOPキーのコードはわかりませんでした。なにしろ押すとテストプログラムが止まってしまいますので・・・。
・CAPSはロックしている間は押下と判断されるみたいです。カナは実際に押下されている間だけです。
・F6だけはどうやってもビットが立ちませんでした。T98-Nextのバグかも?まあ、アクションゲームでF6は使わないでしょうし・・・。
参考文献(PC-9801スーパーテクニック)によると、キーバッファオーバーのBEEP音を鳴らないようにキーボードコントローラにコマンドを送らないといけなかったり、キーリピート中に断続的にキーが放されているように見えるのを、リピート中か手動で連打してるのかを見分けないといけなかったりと、色々大変なようです。残念ながら、ここではこのファンクションについては詳しく説明できません。申し訳ありません。
ウー!98に戻る
ウー!オールドPCに戻る
参考文献
『PC‐9801スーパーテクニック』 1992年 小高輝真、清水和文、速水祐 著 アスキー
『J-3100解析ハンドブック』 1989年 土屋勝著 ナツメ社
『DOS/Vテクニカル・リファレンス・マニュアル』 1993年 芦達剛著 ソフトバンク
|