[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]