手元に実機も実行環境もありませんのでサポート不可です。
文章は執筆当時のものをそのまま掲載していますので、時代・時節と合わない表現が含まれています。
また、一部に半角カナ文字が使用されています。
さてさて、1年ぶりの開講ですね。長々とさぼってました。
今回の講義内容は前回宣言した内容とは少しだけ変えて、まずはキー入力判定から進めたいと思います。
まず、キー入力というものの必要性は言うに及ばないでしょう。
Keyboardというものは、現在のComputerでは最も重要なUser Interfaceの1つで、様々な情報の入力には欠かせないものとなっています。
特にCursorというのは、現在自分がどの情報を参照し、どこに必要な情報を書き込む或いは選択するべきかを示したもので、画面上に展開された種々の情報の選別には欠かせないものです。
という事で、今回はカーソルの移動よりも先にキー入力判定というものを本題に掲げました。
さてこのキー入力の方法というのには幾つかの方式が考えられます。
大体以下の方法があるでしょう。
No. |
手段 |
コメント |
1 |
I/O Portの直接制御 |
電算機の直接制御を目的とするには適するが、Auto Repeatなども全て自身の手で行わなければならず、またKey Bufferの処理の仕方などの問題や、更にKeyboard Deviceの初期化などに苦労を要する場合もあり、あまり実用的とはいいきれないし、BIOSとの両立が困難な場合がある。 |
2 |
BIOSを使用 |
どちらかというと、BIOSを利用した方がKeyboard Deviceの制御には適すると言える(Keyboardは一旦BIOSを経由してからUserに対する反応が示されるようになっているからです)。 |
という事で今回の講義内容は2つのテーマで進めますが、特に後者の方を重要視して進めています。
まず、I/O Portの直接制御によるものですが、PC-9800 Seriesでは特に適さない方式なのかもしれません。上級の技術を持ち、Hardwareに対する知識・BIOSに対する知識が十分に備わっているのであれば問題はないのですが、Keyboard Deviceの初期化には数段階の要素があり、また各段階毎のタイミングの取り方など、あまりにも初心者がするには難しい内容を含むからです。まぁ、本講義ではそこまでの高度なものは考えていませんので、そういう事は割愛します(^^;
逆に、PC-88VA SeriesではKeyboard DeviceのInitializeは全てBIOSが一手に握っており、我々Programmerがそこまで意識する必要はないようになっています。
さてこのようなHardwareの違いはありますが、最終目標としては単にI/O Portから直接Keyboardの状況、特に押しているKeyの状態判別を読み取る事にあります。
大抵の内部資料を記した書籍でれば、Keyboard上の各KeyがどのI/O Portに反映されるようになっているのかを示していますが、そういうのを参考にしながら以下の事を考えられるといいでしょう。
;Sample Program1 For PC-88VA Ideal P186 Model Small Stack 0200h CodeSeg InputCheck: in al,002h ;I/O Port Read test al,000000010b ;Press 'A' Check jnz InputCheck mov ax,04c00h ;Return to PC-Engine(or MS-DOS) int 021h End
この方法では単に「A」を押したらApplicationが終了するようになっています。
内容は特に簡単で、常にA KeyをMapしているI/O Portを読み込み、A Keyが押されたというFlagが立てば終了するというだけで、難しい事は何もしていません。尚PC-9800 Series用がないのは、諸般の事情から動作確認がとれなくなった為と、手元にそのようなLibralyがないため、動作保証が全くとれないものを掲載するべきではないと考えた為です。
複数のKeyを同時に判別したいのであれば、複数のI/O Portを読み込み、1つずつ認識していけばいい事になります。
さて次にBIOSを利用した場合についてですが、これは実にSimpleにできます。
Keyboard Device InitializeからStatus Readまで全てBIOSに任せればよく、先程と同じ動作をするものを組んでみましょう。
;Sample Program2 For PC-88VA Ideal P186 Model Small Stack 0200h CodeSeg mov ax,00500h ;Keyboard Initialize int 082h InputCheck: mov ax,00d02h ;Keyboard Status Read int 082h test ah,000000010b ;Press 'A' Check jz InputCheck mov ax,00400h ;Key Buffer Clear int 082h mov ax,04c00h ;Return to PC-Engine(or MS-DOS) int 021h End
;Sample Program2 For PC-9800 Ideal P186 Model Small Stack 0200h CodeSeg mov ax,00300h ;Keyboard Initialize int 018h InputCheck: mov ax,00403h ;Keyboard Status Read int 018h test ah,000100000b ;Press 'A' Check jz InputCheck KeyBufferClearLoop: mov ax,00100h ;Key Buffer Clear int 018h or bh,bh jz KeyBufferClearEnd xor ax,ax int 018h jmp Short KeyBufferClearLoop KeyBufferClearEnd: mov ax,04c00h ;Return to MS-DOS int 021h End
多少長くなったように思うかもしれませんが、それはBIOSを使う為ですので仕方がありません。
因みに、I/O Portの直接制御でもKeyboard BIOSのInitiailzeを利用すれば、Keyboard Device Initializeができますので、それを利用しても問題はありません。
ただ両Programの結果に大きな違いがあると思います。
前者の方では画面に「A」と表示されるのに対し、後者の方では何も表示されていません。これはKeybuffer Clearを最後にかけているからです。
I/O Portだけを利用する場合にはどうしてもBIOSにためられた情報を抑え切れないのに対し、うまくBIOSを利用すればそのような問題はありません。
しかし、I/O Portだけを利用する事に固執せずにBIOSを併用するようにすれば、恐らくにして問題はないでしょう。というより、BIOSというのはあくまで補助動作用のもので、面倒な処理を全て任せてしまうという為のものと考えるべきなのかも知れませんが。
プログラミング時のまめ知識その3−DOSによるKeyboard入力判定−
やる事は大変簡単です。DOS Commandを1個用いるだけです。
Ideal P186 Model Small Stack 0200h CodeSeg InputCheck: mov ah,001h int 021h sub al,020h cmp al,'A' ;Press 'A' Check jnz InputCheck mov ax,04c00h ;Return to PC-Engine(or MS-DOS) int 021h End
DOS互換のSoftwareなら、こういう方式(或いはそれに近いもの)でやってる事が殆どだと思います。
では次に複数入力の例を示しましょう。
;Sample Program3 For PC-88VA Ideal P186 Model Small Stack 0200h CodeSeg call KeyboardInitialize MainRoutine: call KeyInputCheck test al,000010000b jz MainRoutine call KeyBufferClear mov ax,04c00h int 021h Proc KeyboardInitialize Near push ax mov ax,00500h int 082h pop ax ret EndP Proc KeyInputCheck Near pushf push bx cx ds cld mov ax,cs mov ds,ax mov si,Offset InputKeyTable xor bx,bx mov cx,5 KeyInputCheckLoop: push cx lodsb mov ah,00dh int 082h lodsb mov cl,al shr ah,cl rcl bl,1 pop cx loop KeyInputCheckLoop mov ax,bx pop ds cx bx popf ret EndP InputKeyTable: db 009h,1 ;Stop db 008h,2 ;Up db 00ah,2 ;Down db 00ah,3 ;Left db 008h,3 ;Right Proc KeyBufferClear Near push ax mov ax,00400h int 082h pop ax ret EndP End
;Sample Program3 For PC-9800 Ideal P186 Model Small Stack 00200h .Code call KeyboardInitialize MainRoutine: call KeyInputCheck test al,000010000b jz MainRoutine call KeyBufferClear mov ax,04c00h int 021h Proc KeyboardInitialize Near push ax mov ax,00300h int 018h pop ax ret EndP Proc KeyInputCheck Near pushf push bx cx ds cld mov ax,cs mov ds,ax mov si,Offset InputKeyTable xor bx,bx mov cx,5 KeyInputCheckLoop: push cx lodsb mov ah,004h int 018h lodsb mov cl,al shr ah,cl rcl bl,1 pop cx loop KeyInputCheckLoop mov ax,bx pop ds cx bx popf ret EndP InputKeyTable: db 00ch,1 ;Stop db 007h,3 ;Up db 007h,6 ;Down db 007h,4 ;Left db 007h,5 ;Right Proc KeyBufferClear Near push ax bx KeyBufferClearLoop: mov ax,00100h int 018h or bh,bh jz KeyBufferClearEnd xor ax,ax int 018h jmp Short KeyBufferClearLoop KeyBufferClearEnd: pop bx ax ret EndP End
この方法でやっている事は、Table処理を利用しているというぐらいで大した事は何もしていません(尚、Stop KeyとCursor Keyの判別をしていますが、Stop Keyを押さない限り終了しませんし、反応はないようになっています)。
またBIOSによる入力判定をしていますが、これをI/O Portによるものと入れ替えても、そう動作に問題はないでしょう。というより、前述してきた方法はあくまで別々に行った場合を取り上げただけで、実際にはやりたい事だけを限定すれば、ここまで簡単にできるという事を示したかっただけのものです。
さて、Tableにかかれているものですが、前者はKey Mapの何れのAdderssを読むのか、を示し、後者の列はそのAddressの何Bit目を読むのかを示しています。
この方法を利用すれば、ほぼ大抵の単一のKey入力には応用できます。
現実私も多用する程のものです。
さて、今回の講義内容はまずはここまでとします。
次回は実際にCursorを表示し、Cursor Keyによって移動する所までを示しましょう。
手元に実機も実行環境もありませんのでサポート不可です。
文章は執筆当時のものをそのまま掲載していますので、時代・時節と合わない表現が含まれています。
また、一部に半角カナ文字が使用されています。