[Back to KEYBOARD SWAG index] [Back to Main SWAG index] [Original]
{
Well, I got it figured out now! Kudos go to you, to Ralf Brown and his
list of ports, the great state of Ohio, the Church of the SubGenius, and
most of all, Bill Seiler.
Who is Bill Seiler? Well, did any of you ever play that old (1985-1986)
game called "Space War"? I did, and still do; and in fact, I registered
the game (it IS shareware, after all), and got the source code. It's all
in ASM, and a lot of it still mystifies me; but I was able to figure out
how he does his keyboard interrupt. Yet another advantage of registering
this shareware product, five years ago!
Here's my Pascal version, with significant line numbers:
var port60h, port61h: byte;
keydown: array[0 .. 127] of boolean;
procedure newkbdint; interrupt;
begin
1 port60h := port[$60];
2 keydown[port60h and $7f] := (port60h <= $7f);
3 port61h := port[$61];
4 port[$61] := port61h or $80;
5 port[$61] := port61h;
6 port[$20] := $20;
end;
1 - Read the port.
2 - Store the new key status for whatever key: either up or down.
3 - Read in port 61h, the system control port.
4 - Send the value back to 61h with the high bit set to "1" to reset
the keyboard.
5 - Send the original, unadulterated value back to 61h.
6 - The boring old End of Interrupt instruction. This line might not
even be necessary! It was only after testing that procedure out
and pasting it into this message, that I noticed that I had left
the EOI off the procedure. But it seemed to work all right without
it. It seems to work just fine *with* it too, so it's probably
best to keep it.
And, for the pure of heart: the same routine in BASM, which does not
need "port60h" and "port61h" for intermediate storage:
}
procedure newkbdint; assembler; { new keyboard handler }
asm
push ax { push registers }
push bx
push ds
mov ax, SEG @Data
mov ds, ax
in al, 60h
mov bx, ax
and bx, 007fh { switch high bit of BX to zero }
and al, 80h { check high bit of port value }
jz @press
@release: { high bit = 1: "release" code }
mov byte ptr keydown[bx], 00h { write 00 to "down" array element }
jmp @done
@press: { high bit = 0: "press" code }
mov byte ptr keydown[bx], 01h { write 01 to "down" array element }
@done:
in al, 61h { read port 61h, system ctrl port }
mov ah, al { save value to AH }
or al, 80h { set top bit to "1" - reset kbd }
out 61h, al { write out value to port }
xchg ah, al { put original value back into AL }
out 61h, al { rewrite original value in AL }
mov al, 20h { generate End of Interrupt }
out 20h, al
pop ds { pop registers }
pop bx
pop ax
iret { return }
end;
[Back to KEYBOARD SWAG index] [Back to Main SWAG index] [Original]