C言語講座 第一回 キー入力

始めに

ポケコンの、BASIC には INKEY$ があるのに、C言語には、getch()kbhit() しかないんじゃ~ というわけで、第一回のC言語 講座は、キー入力を扱うことにします。

其の壱

まず、getch()kbhit() を組み合わせて、

int inkey()
{
  if(kbhit())
    return getch();
  return 0;
}

main()
{
  int c;

  while(1) {
    c = inkey();
    printf("KEY = %c[%02X] \n", c, c);
  }
}

として、キーを入力しようとしても、なぜキーを入力すると表示がとまってしまうのかというと、 おそらく getch() が内部でキー入力を待っているので停止しているからなのだと考えられます。

其の弐

そこで、C言語でキーを入力するために call() 命令を使ってみようという事になります。
以下は、「未完成な張りぼて」からの引用です ^_^;
main() は上のプログラムを使ってください。

char inkeyt1(void){	/*キー入力関数軽量型(不都合あり)*/
    static char *p="へSセヘVセ2ェ□ノ";	/*□はスペース*/
    call((unsigned)p ,0);
        return (peek(0x20aa));
}

「未完成な張りぼて」では詳しく触れられていないようなので、逆アセして解析してみます。
call() で呼び出している、p が一番肝心なプログラムです。

ORG   100H
CALL  0BE53H      ;  0xBE53 をコール
CALL  0BE56H      ;  0xBE56 をコール
LD    (20AAH),A   ;  0x20AA 番地に A レジスタ値を書き出し
RET               ;  戻る
END

てな具合です。
0xBE53 は キー入力 の ROM 内関数で、
0xBE560xBE53 からの戻り値を "アスキーコードに変換" する ROM 内関数のようです。
(‥のようです、というのは、どこにも記載がないからです。結果からするとおそらく、ということです。)
(2005/02/06)教員用の指導書に記載がありました。

で、どんな不具合が発生するかというと、0x20AA 番地に書き出すことが曲者であって、 もし 0x20AA 番地に他のプログラムがあった場合にはそれと書きつぶしてしまうことが問題なのです。
そこで、LD (20AAH),ALD (0FFH),A にしてみたら、

int inkey()
{
  static char *p="へSセヘVセ2\xff\0ノ";
  call((unsigned)p ,0);
  return peek(0x20aa);
}

こうなりました。
しかし、これでもまだ、不安が残ります。 もし、0xFF 番地にステータスを記録するプログラムだった場合は?

其の参

そこで、call() をおさらいしてみます。

unsigned call(unsigned adr, void * arg_HL);
  adr    : 機械語の先頭アドレス
  arg_HL : HL レジスタに渡される値
  戻り値 : HL レジスタの値

だそうです。
そこで、この戻り値を利用し値を返すことにします。
まず、アセンブラソースです。

ORG     100H
CALL    0BE53H      ;  0xBE53 をコール
CALL    0BE56H      ;  0xBE56 をコール
LD      L,A         ;  L レジスタに A レジスタ値を書き出し
RET                 ;  戻る
END

根本的には、変化していないのですが、LD (0FFH),A の部分を変更しました。
なんか使い方が間違っているような気もしますが、C言語のソースは、こうなりました。

int inkey()
{
  static char *p="ヘSセヘVセoノ"; /* 全て全角にしてあります */
  return call((unsigned)p,0);
}

結構すっきりしたと思います。
ちなみに、このプログラムは、同時にはキーを取得できません。

call() で機械語を呼び出し、結果を HL レジスタを戻り値としてキーコードを返しています。
H レジスタは、呼び出し時に 0 になっているので結果的に L レジスタの値が戻ってくるわけです。

最後に

長々と書いた割には、重要なのは、上のプログラムだけ(しかも、他人のふんどしで相撲を取っているし)。
まあ、第一回の講座は、これでお開きです。
最後に、プログラムとキーコード表をのせたいと思います。
長々とお付き合いありがとうございました。

プログラム inkey.h

 名前を inkey.h に変え、
 #include "inkey.h"
 として読込むか、直接記述してお使いください。

キーコード表
下位\上位 0 1 2 3 4 5 6 7 D F
0 入力なし 2ndF スペース 0 @ P p ASMBL
1 BASIC カナ ! 1 A Q a q BASE-n
2 TEXT INS " 2 B R b r コントラスト
3 C DRG # 3 C S c s
4 STAT CAPS $ 4 D T d t
5 ANS % 5 E U e u
6 OFF (-) & 6 F V f v
7 P⇔NP CONST ' 7 G W g w
8 BS (CONST) ( 8 H X h x
9 DEL R・CM ) 9 I Y i y
A TAB M+ * : J Z j z
B CA M- + ; K [ k {
C CLS , < L \ l |
D ENTER - = M ] m }
E DIGIT . > N ^ n ~ 他のキー
F F⇔E / ? O _ o

文字 特殊なキーの名前
文字 [2ndF] または [SHIFT] を押したときの名前

履歴

2004/02/24
公開
2005/02/06
注釈追加
構成変更
前 | C言語講座 第一回 キー入力 |

2008年07月20日 公開 / 2008年08月10日 更新