GophHub - zajo/appler/src/KEYBOARD.ASM


Raw File

;  _____________________________________________
; |                                             |
; |  Project:   APPLER                          |
; |  File:      KEYBOARD.ASM                    |
; |  Compiler:  16-bit TASM (2.5)               |
; |                                             |
; |  Subject:   Keyboard Manager                |
; |                                             |
; |  Author:    Emil Dotchevski                 |
; |_____________________________________________|

                include GLOBALS.INC
                include INTERFAC.INC

Keyboards       group   Keyboard,SimKbd
Keyboard        segment public
                assume  cs:Keyboard, ds:Keyboard, es:Emulate, ss:Data


DATA_PORT       =       60h
COMMAND_PORT    =       64h
OUTPUT_FULL     =       01h             ; Output buffer full flag bit
INPUT_EMPTY     =       02h             ; Input buffer empty flag bit
DISABLE_KEYBOARD=       0ADh            ; Disable keyboard command code
ENABLE_KEYBOARD =       0AEh            ; Enable keyboard command code
LED_SET         =       0EDh            ; Set keyboard LEDs command code
ACKNOWLEDGE     =       0FAh            ; Keyboard ACK
TIME_OUT        =       0FFFFh          ; 8042 time out counter value

K_KeyboardRet1  label   byte
SetLEDs         proc    far                     ; AL - LED data
                push    ax
                mov     al,DISABLE_KEYBOARD
                call    K_SendCommand
                jc      SetLEDs_Exit
                mov     al,LED_SET
                call    K_SendData
                jc      SetLEDs_Exit
                pop     ax
                push    ax
                call    K_SendData
SetLEDs_Exit:   mov     al,ENABLE_KEYBOARD
                out     COMMAND_PORT,al
                pop     ax
                ret
SetLEDs         endp
LightsData      db      0

K_KeyboardRet2  label   byte
K_SendCommand   proc    far
                push    ax
                call    WaitInputEmpty
                jc      K_SC_Ret
                out     COMMAND_PORT,al
                call    WaitOutputFull
                jc      K_SC_Ret
                in      al,DATA_PORT
                call    WaitInputEmpty
K_SC_Ret:       pop     ax
                ret
K_SendCommand   endp

K_KeyboardRet3  label   byte
K_SendData      proc    far
                push    ax
                call    WaitInputEmpty
                jc      K_SD_Ret
                out     DATA_PORT,al
                call    WaitOutputFull
                jc      K_SD_Ret
                in      al,DATA_PORT
                call    WaitInputEmpty
K_SD_Ret:       pop     ax
                ret
K_SendData      endp

K_KeyboardRet4  label   byte
K_GetData       proc    far
                in      al,DATA_PORT
                call    WaitInputEmpty
                ret
K_GetData       endp

WaitInputEmpty  proc    near
                push    ax cx
                mov     cx,TIME_OUT
WIE_Loop:       in      al,COMMAND_PORT
                test    al,INPUT_EMPTY
                jz      WIE_Exit
                loop    WIE_Loop
                stc
WIE_Exit:       pop     cx ax
                ret
WaitInputEmpty  endp

WaitOutputFull  proc    near
                push    ax cx
                mov     cx,TIME_OUT
WOF_Loop:       in      al,COMMAND_PORT
                test    al,OUTPUT_FULL
                jz      WOF_Exit
                loop    WOF_Loop
                stc
WOF_Exit:       pop     cx ax
                ret
WaitOutputFull  endp


k_BufferFlag    db      0
k_BuffPtr1      db      0
k_BuffPtr2      db      0
k_Buffer        db      64 dup (?)

ClearBuffer     proc    far
                mov     cs:k_BuffPtr1,0
                mov     cs:k_BuffPtr2,0
                ret
ClearBuffer     endp

PutBuffer       proc    near
                test    C000,10000000b
                jz      k_NoBuff
                test    k_BufferFlag,1
                jz      k_NoBuff
                xor     bx,bx
                mov     bl,k_BuffPtr2
                mov     k_Buffer[bx],al
                inc     bl
                cmp     bl,size k_Buffer
                jb      PB_1
                xor     bx,bx
PB_1:           cmp     bl,k_BuffPtr1
                je      PB_Ret
                mov     k_BuffPtr2,bl
                jmp     PB_Ret
k_NoBuff:       mov     C000,al
PB_Ret:         ret
PutBuffer       endp

GetBuffer       proc    far
                pushf
                push    ax bx ds es
                push    cs
                pop     ds
                cmp     k_BufferFlag,0
                jz      GB_Ret
                mov     ax,Emulate
                mov     es,ax
                xor     bx,bx
                mov     bl,k_BuffPtr1
                mov     al,k_Buffer[bx]
                cmp     bl,k_BuffPtr2
                je      GB_Ret
                inc     bl
                cmp     bl,size k_Buffer
                jb      GB_1
                xor     bx,bx
GB_1:           mov     k_BuffPtr1,bl
                mov     [C000],al
GB_Ret:         pop     es ds bx ax
                popf
                ret
GetBuffer       endp

get_table_ofs   proc    far
                push    ax
                mov     al,bl
                xor     bx,bx
                test    al,M_ALT
                mov     bl,2 shl 1
                jnz     gto_ModeOK
                test    al,M_CTRL
                mov     bl,1 shl 1
                jnz     gto_ModeOK
                test    al,M_CAPS_LOCK
                jz      gto_not_caps
                test    al,M_LEFT_SHIFT or M_RIGHT_SHIFT
                mov     bl,4 shl 1
                jnz     gto_ModeOK
                mov     bl,3 shl 1
                jmp     gto_ModeOK
gto_not_caps:   test    al,M_LEFT_SHIFT or M_RIGHT_SHIFT
                mov     bl,5 shl 1
                jnz     gto_ModeOK
                test    al,M_NUM_LOCK
                mov     bl,6 shl 1
                jnz     gto_ModeOK
                xor     bx,bx
gto_ModeOK:     pop     ax
                ret
get_table_ofs   endp

k_Fire1         =       80h
k_Fire2         =       81h
k_LeftArrow     =       82h
k_RightArrow    =       83h
k_UpArrow       =       84h
k_DownArrow     =       85h
None            =       86h
Ctrl            =       87h
Lshift          =       88h
Rshift          =       89h
Caps            =       8Ah
ALT             =       8Bh
k_Reset         =       8Ch
k_Pause         =       8Dh
k_F1            =       8Eh
k_F2            =       8Fh
k_F3            =       90h
k_F4            =       91h
k_F5            =       92h
k_F6            =       93h
k_F7            =       94h
k_F8            =       95h
k_F9            =       96h
k_F10           =       97h
k_DosShell      =       98h
k_QuitAppler    =       99h
k_F11           =       9Ah
k_F12           =       9Bh
k_NumLock       =       9Ch

k_KeyPressed    db      1
k_Flags         dw      0
k_KeyCode       db      0
k_ScanCode      db      0
k_Shifts        dw      0
k_Table         dw      k_AppleTable
k_AppleTable    dw      a_NormalTable           ; Normal table
                dw      a_CtrlTable             ; Ctrl pressed
                dw      a_AltTable              ; Ctrl and Alt pressed
                dw      a_CapsTable             ; Caps Lock mode
                dw      a_CpsShfTable           ; Shift in Caps Lock mode
                dw      a_ShiftTable            ; Shift mode
                dw      a_NumTable              ; Num Lock mode
k_DebugTable    dw      d_NormalTable
                dw      d_NormalTable
                dw      d_AltTable
                dw      d_CapsTable
                dw      d_CpsShfTable
                dw      d_ShiftTable
                dw      d_NormalTable
k_KbdSetupTable dw      k_NormalTable
                dw      k_NormalTable
                dw      k_AltTable
                dw      k_NormalTable
                dw      k_NormalTable
                dw      k_NormalTable
                dw      k_NormalTable


k_int09:        push    ax
                in      al,DATA_PORT
                push    ax
                in      al,61h
                or      al,11000000b
                jmp     $+2
                out     61h,al
                and     al,01111111b
                jmp     $+2
                out     61h,al
                mov     al,20h
                out     20h,al
                pop     ax
                call    far ptr KeyStopPlay
                xchg    sp,bp
                or      [bp+6],ax
                xchg    sp,bp
k_int09_iret:   pop     ax
                iret

KeyStopPlay:    or      al,al
                js      Key
                call    SimKbdClr
Key:            push    bx si ds es
                push    cs
                pop     ds
                mov     k_Flags,0
                test    k_PauseFlag,1
                jnz     k_KeyPause
                mov     bx,Emulate
                mov     es,bx
                mov     ah,al
                xor     bx,bx
                mov     bl,ah
                and     bl,01111111b
                cmp     bl,58h
                ja      k_ret
                mov     al,bl
                mov     bx,k_Shifts
                call    get_table_ofs
                mov     si,k_Table
                mov     bx,[si][bx]
                xlat
                mov     k_KeyCode,al
                or      al,al
                js      k_SpecialKey
                or      ah,ah
                js      k_ret
                or      al,10000000b
                call    PutBuffer
k_record_ret:   mov     al,ah
                call    RecordKey
k_ret:          and     ah,01111111b
                mov     k_ScanCode,ah
                mov     ax,k_Flags
                pop     es ds si bx
                retf

k_KeyPause:     or      al,al
                js      k_ret
                mov     k_PauseFlag,0
                jmp     k_ret

k_SpecialKey:   cmp     ah,k_OldSpcKey
                je      k_ret
                push    ax
                and     al,01111111b
                or      ah,ah
                mov     si,offset k_KeyOnSub
                jns     k_SK_on
                mov     si,offset k_KeyOffSub
                xor     ah,ah
k_SK_on:        mov     k_OldSpcKey,ah
                xor     bh,bh
                mov     bl,al
                shl     bx,1
                mov     ax,k_Shifts
                call    [si][bx]
                mov     k_Shifts,ax
                mov     k_KeyPressed,1
                pop     ax
                jmp     k_record_ret
k_OldSpcKey     db      0
k_KeyOnSub      dw      k_Fire1_ON,k_Fire2_ON,k_LA_ON,k_RA_ON,k_UA_ON,k_DA_ON
                dw      k_None
                dw      k_Ctrl_ON,k_Lshift_ON,k_Rshift_ON,k_Caps_ON,k_ALT_ON
                dw      k_Reset_ON,k_Pause_ON
                dw      k_F_ON,k_F_ON,k_F_ON,k_F_ON,k_F_ON,k_F_ON,k_F_ON,k_F_ON,k_F_ON,k_F_ON
                dw      k_F_ON,k_F_ON
                dw      k_None,k_F12_ON,k_Num_ON
k_KeyOffSub     dw      k_Fire1_OFF,k_Fire2_OFF,k_LA_OFF,k_RA_OFF,k_UA_OFF,k_DA_OFF
                dw      k_None
                dw      k_Ctrl_OFF,k_Lshift_OFF,k_Rshift_OFF,k_Caps_OFF,k_ALT_OFF
                dw      k_Reset_OFF,k_None
                dw      k_None,k_None,k_None,k_None,k_None,k_None,k_None,k_None,k_None,k_None
                dw      k_None,k_None
                dw      k_None,k_None,k_Num_OFF

k_Ctrl_OFF:     and     al,not M_CTRL
k_None:         ret
k_Lshift_OFF:   and     al,not M_LEFT_SHIFT
                ret
k_Rshift_OFF:   and     al,not M_RIGHT_SHIFT
k_Caps_OFF:     ret
k_ALT_OFF:      and     al,not M_ALT
                ret
k_Reset_OFF:    and     ResetFlag,11111110b
                mov     C000,0
                ret
k_Fire1_OFF:    mov     es:JoyButton1,7Fh
                ret
k_Fire2_OFF:    mov     es:JoyButton2,7Fh
                ret
k_LA_OFF:       and     es:JoyStick,not 00000001b
                ret
k_RA_OFF:       and     es:JoyStick,not 00000010b
                ret
k_UA_OFF:       and     es:JoyStick,not 00000100b
                ret
k_DA_OFF:       and     es:JoyStick,not 00001000b
                ret

k_Ctrl_ON:      or      al,M_CTRL
                ret
k_Lshift_ON:    cmp     k_ScanCode,060h
                je      k_Lshift_ON_ret
                or      al,M_LEFT_SHIFT
k_Lshift_ON_ret:ret
k_Rshift_ON:    cmp     k_ScanCode,060h
                je      k_Rshift_ON_ret
                or      al,M_RIGHT_SHIFT
k_Rshift_ON_ret:ret
k_Caps_ON:      xor     al,M_CAPS_LOCK
                push    ax
                xor     LightsData,00000100b
                mov     al,LightsData
                call    SetLEDs
                pop     ax
                ret
k_ALT_ON:       or      al,M_ALT
                ret
k_Num_ON:       xor     al,M_NUM_LOCK
                push    ax
                xor     LightsData,00000010b
                mov     al,LightsData
                call    SetLEDs
                test    al,00000010b
                mov     ss:C0xxRead[2*61h], offset C0612r
                mov     ss:C0xxRead[2*62h], offset C0612r
                mov     ss:C0xxRead[2*64h], offset C0645r
                mov     ss:C0xxRead[2*65h], offset C0645r
                jz      k_Num_ON1
                mov     ss:C0xxRead[2*61h], offset C061r
                mov     ss:C0xxRead[2*62h], offset C062r
                mov     ss:C0xxRead[2*64h], offset C064r
                mov     ss:C0xxRead[2*65h], offset C065r
                mov     es:JoyStick,0
k_Num_ON1:      pop     ax
k_Num_OFF:      ret
k_Fire1_ON:     mov     es:JoyButton1,0FFh
                ret
k_Fire2_ON:     mov     es:JoyButton2,0FFh
                ret
k_LA_ON:        or      es:JoyStick,00000001b
                ret
k_RA_ON:        or      es:JoyStick,00000010b
                ret
k_UA_ON:        or      es:JoyStick,00000100b
                ret
k_DA_ON:        or      es:JoyStick,00001000b
                ret
k_Reset_ON:     test    al,M_CTRL
                jz      k_Reset_ON_J
                test    ResetFlag,00000001b
                jnz     k_Reset_ON_J
                or      ResetFlag,00000001b
                jmp     RESET
k_Reset_ON_J:   ret

k_PauseFlag     db      0
k_OldIRQ        db      ?
k_Pause_ON:     push    ax
                in      al,21h
                mov     k_OldIRQ,al
                mov     al,11111101b
                out     21h,al
                mov     k_PauseFlag,1
                mov     al,00000111b
                call    SetLEDs
                sti
k_PauseLoop:    test    k_PauseFlag,1
                jnz     k_PauseLoop
                cli
                mov     al,k_OldIRQ
                out     21h,al
                mov     al,LightsData
                call    SetLEDs
                pop     ax
                and     al,not M_CTRL
                ret

k_ProcessIDs    db      PID_DEBUGGER
                db      PID_FILE_MANAGER
                db      PID_FLOPPY_DISK_MANAGER
                db      PID_KEYBOARD_SETUP
                db      PID_DONT_SWITCH
                db      PID_DONT_SWITCH
                db      PID_DONT_SWITCH
                db      PID_DONT_SWITCH
                db      PID_ABOUT_SCREEN
                db      PID_HELP_SCREEN
                db      PID_DOS_SHELL
                db      PID_QUIT_APPLER

k_F_ON:         push    es
                mov     ax,seg RetWhere?
                mov     es,ax
                assume  es:seg RetWhere?
                shr     bx,1
                sub     bl,k_F1 and 01111111b
                mov     al,k_ProcessIDs[bx]
                mov     k_OldSpcKey,0
                mov     es:RetWhere?,al
                or      word ptr k_Flags,0000000100000000b
                pop     es
                mov     ax,k_Shifts
                and     al,not(M_CTRL or M_LEFT_SHIFT or M_RIGHT_SHIFT or M_ALT)
                ret
                assume  es:Emulate

k_F12_ON:       xor     es:synchro_push_ax,0FAh xor 0C3h
                ret


a_NormalTable   db      None,1Bh,'1234567890-=',8                 ; Normal Table
                db      9,'QWERTYUIOP[]',0Dh
                db      Ctrl,'ASDFGHJKL;',27h,'`'
                db      LShift,'\ZXCVBNM,./',RShift,'*'
                db      ALT,' ',Caps
                db      k_F1,k_F2,k_F3,k_F4,k_F5,k_F6,k_F7,k_F8,k_F9,k_F10
                db      k_NumLock,k_Reset,None,0Bh,None,'-'
                db      8,None,15h,'+',None,0Ah,None,9,4
                db      None,None,None,None,k_F12

a_CtrlTable     db      None,1Bh,'1234567890-=',8                 ; CtrlTable
                db      9,11h,17h,5,12h,14h,19h,15h,9,0Fh,10h,1Bh,1Dh,0Dh
                db      Ctrl,1,13h,4,6,7,8,0Ah,0Bh,0Ch,';',27h,1Eh
                db      LShift,0,1Ah,18h,3,16h,2,0Eh,0Dh,',./',RShift,'*'
                db      ALT,' ',Caps
                db      k_F1,k_F2,k_F3,k_F4,k_F5,k_F6,k_F7,k_F8,k_F9,k_F10
                db      k_Pause,k_Reset,None,0Bh,None,'-'
                db      8,None,15h,'+',None,0Ah,None,9,k_Reset
                db      None,None,None,None,k_F12

a_ShiftTable    db      None,1Bh,'!@#$%^&*()_+',15h               ; ShiftTable
                db      9,'qwertyuiop{}',0Dh
                db      Ctrl,'asdfghjkl:"~'
                db      LShift,'|zxcvbnm<>?',RShift,'*'
                db      ALT,' ',Caps
                db      k_F1,k_F2,k_F3,k_F4,k_F5,k_F6,k_F7,k_F8,k_F9,k_F10
                db      k_NumLock,k_Reset,'789-456+1230.'
                db      None,None,None,None,k_F12

a_CapsTable     db      None,1Bh,'1234567890-=',8                 ; CapsTable
                db      9,'qwertyuiop[]',0Dh
                db      Ctrl,'asdfghjkl;',27h,'`'
                db      LShift,'\zxcvbnm,./',RShift,'*'
                db      ALT,' ',Caps
                db      k_F1,k_F2,k_F3,k_F4,k_F5,k_F6,k_F7,k_F8,k_F9,k_F10
                db      k_NumLock,k_Reset,None,0Bh,None,'-'
                db      8,None,15h,'+',None,0Ah,None,9,4
                db      None,None,None,None,k_F12

a_CpsShfTable   db      None,1Bh,'!@#$%^&*()_+',15h               ; CpsShfTable
                db      9,'QWERTYUIOP[]',0Dh
                db      Ctrl,'ASDFGHJKL:"~'
                db      LShift,'|ZXCVBNM,./',RShift,'*'
                db      ALT,' ',Caps
                db      k_F1,k_F2,k_F3,k_F4,k_F5,k_F6,k_F7,k_F8,k_F9,k_F10
                db      k_NumLock,k_Reset,'789-456+1230.'
                db      None,None,None,None,k_F12

a_AltTable      db      None,k_DosShell,'1234567890-=',8 ; AltTable
                db      9,11h,17h,5,12h,14h,19h,15h,9,0Fh,10h,1Bh,1Dh,0Dh
                db      Ctrl,1,13h,4,6,7,8,0Ah,0Bh,0Ch,';',27h,1Eh
                db      LShift,0,1Ah,k_QuitAppler,3,16h,2,0Eh,0Dh,',./',RShift,'*'
                db      ALT,' ',Caps
                db      k_F1,k_F2,k_F3,k_F4,k_F5,k_F6,k_F7,k_F8,k_F9,k_F10
                db      k_NumLock,k_Reset,None,0Bh,None,'-'
                db      8,None,15h,'+',None,0Ah,None,9,None
                db      None,None,None,None,k_F12

a_NumTable      db      None,1Bh,'1234567890-=',8          ; Num Table
                db      9,'QWERTYUIOP[]',0Dh
                db      Ctrl,'ASDFGHJKL;',27h,'`'
                db      LShift,'\ZXCVBNM,./',RShift,'*'
                db      ALT,' ',Caps
                db      k_F1,k_F2,k_F3,k_F4,k_F5,k_F6,k_F7,k_F8,k_F9,k_F10
                db      k_NumLock,k_Reset,None,k_UpArrow,None,'-'
                db      k_LeftArrow,None,k_RightArrow,'+',None,k_DownArrow,None,k_Fire1,k_Fire2
                db      None,None,None,None,k_F12



;  1 Home
;  2 End
;  3 PgUp
;  4 PgDn
;  5 Left
;  6 Right
;  7 Up
;  8 Down
;  9 Ins
;  A Del
;  B BS
;  C Esc
;  D Tab
;  E F1
;  F F2
; 10 F3
; 11 F4
; 12 F5
; 13 F6
; 14 F7
; 15 F8
; 16 F9
; 17 F10
; 18 Enter
; 19 Cntr
; 1A Dos Shell
; 1B Quit

d_NormalTable   db      None,0Ch,'1234567890-=',0Bh
                db      0Dh,'qwertyuiop[]',18h
                db      Ctrl,'asdfghjkl;',27h,'`'
                db      LShift,'\zxcvbnm,./',RShift,'*'
                db      ALT,' ',Caps
                db      0Eh,0Fh,10h,11h,12h,13h,14h,15h,16h,17h
                db      k_NumLock,None,1,7,3,'-'
                db      5,19h,6,'+',2,8,4,9,0Ah
                db      None,None,None,None,None

d_ShiftTable    db      None,0Ch,'!@#$%^&*()_+',0Bh
                db      0Dh,'QWERTYUIOP{}',18h
                db      Ctrl,'ASDFGHJKL:"~'
                db      LShift,'|ZXCVBNM<>?',RShift,'*'
                db      ALT,' ',Caps
                db      0Eh,0Fh,10h,11h,12h,13h,14h,15h,16h,17h
                db      k_NumLock,None,1,7,3,'-'
                db      5,19h,6,'+',2,8,4,9,0Ah
                db      None,None,None,None,None

d_CapsTable     db      None,0Ch,'1234567890-=',0Bh
                db      0Dh,'QWERTYUIOP[]',18h
                db      Ctrl,'ASDFGHJKL;',27h,'`'
                db      LShift,'\ZXCVBNM,./',RShift,'*'
                db      ALT,' ',Caps
                db      0Eh,0Fh,10h,11h,12h,13h,14h,15h,16h,17h
                db      k_NumLock,None,1,7,3,'-'
                db      5,19h,6,'+',2,8,4,9,0Ah
                db      None,None,None,None,None

d_CpsShfTable   db      None,0Ch,'!@#$%^&*()_+',0Bh
                db      0Dh,'qwertyuiop{}',18h
                db      Ctrl,'asdfghjkl:"~'
                db      LShift,'|zxcvbnm<>?',RShift,'*'
                db      ALT,' ',Caps
                db      0Eh,0Fh,10h,11h,12h,13h,14h,15h,16h,17h
                db      k_NumLock,None,1,7,3,'-'
                db      5,19h,6,'+',2,8,4,9,0Ah
                db      None,None,None,None,None

d_AltTable      db      None,1Ah,'1234567890-=',0Bh
                db      0Dh,'qwertyuiop[]',18h
                db      Ctrl,'asdfghjkl;',27h,'`'
                db      LShift,'\z',1Bh,'cvbnm,./',RShift,'*'
                db      ALT,' ',Caps
                db      0Eh,0Fh,10h,11h,12h,13h,14h,15h,16h,17h
                db      k_NumLock,None,1,7,3,'-'
                db      5,19h,6,'+',2,8,4,9,0Ah
                db      None,None,None,None,None

k_NormalTable   db      None,'..............'
                db      '..............'
                db      Ctrl,'............'
                db      LShift,'...........',RShift,'.'
                db      ALT,'.',Caps
                db      0Eh,0Fh,10h,11h,12h,13h,14h,15h,16h,17h
                db      k_NumLock,None,'....'
                db      '.........'
                db      None,None,None,None,None

k_AltTable      db      None,1Ah,'.............'
                db      '..............'
                db      Ctrl,'............'
                db      LShift,'..',1Bh,'........',RShift,'.'
                db      ALT,'.',Caps
                db      0Eh,0Fh,10h,11h,12h,13h,14h,15h,16h,17h
                db      k_NumLock,None,'....'
                db      '........',1Bh
                db      None,None,None,None,None
Keyboard        ends



SimKbd          segment public
                assume  cs:SimKbd,ds:SimKbd,es:Emulate

; Entry:
;   DS:SI -> keys
;   CF    -- keys format type: 1 - single, 0 - double
SimKbdRq        proc    far
                push    ax cx dx
                mov     al,0
                jnc     SKR_1
                inc     al
SKR_1:          mov     cs:SK_SpeedType,al
                mov     word ptr cs:SK_Address,si
                mov     word ptr cs:SK_Address[2],ds
                xor     ax,ax
                mov     al,cs:SK_Speed
                mov     cx,cs
                mov     dx,offset SimKbdTimer
                call    TimerReq
                pop     dx cx ax
                ret
SimKbdRq        endp

SimKbdClrKeys   db      0
SimKbdClr       proc    far
                push    si ds
                push    cs
                pop     ds
                mov     si,offset SimKbdClrKeys
                stc
                call    SimKbdRq
                pop     ds si
                ret
SimKbdClr       endp

key_taken       proc    far
                mov     cs:SK_WaitFlag,0
                ret
key_taken       endp

SK_SpeedType    db      1
SK_Address      dd      ?
SK_Speed        db      1
SK_WaitFlag     db      0
SimKbdTimer     proc    far
                mov     ax,seg C000
                mov     es,ax
                lds     si,cs:SK_Address
                cmp     cs:SK_WaitFlag,0
                jz      SK_ok
                mov     ax,1
                mov     cx,cs
                mov     dx,offset SimKbdTimer
                call    TimerReq
                ret
SK_ok:          cld
                lodsb
                or      al,al
                jz      SK_Ret
                cmp     al,0FFh
                jne     SK_DoIt
                lodsb
                mov     cs:SK_Speed,al
                jmp     SK_CallRq
SK_DoIt:        mov     es:C000,0
                call    far ptr Key
                mov     bl,es:C000
                mov     cs:SK_WaitFlag,bl
                mov     bx,seg TimerFlags
                mov     es,bx
                assume  es:seg TimerFlags
                or      es:TimerFlags,ax
                cmp     cs:SK_SpeedType,1
                je      SK_CallRq
                lodsb
                mov     cs:SK_Speed,al
SK_CallRq:      cmc
                call    SimKbdRq
SK_Ret:         ret
SimKbdTimer     endp

;------------------------------------------------------ Recording & Playback ---

; Entry:
;   ES:DI -> buffer
;   CX    -- buffer length
StartRecord     proc    far
                push    ax ds
                push    cs
                pop     ds
                mov     RK_RecordAddrLo,di
                mov     RK_RecordAddrHi,es
                mov     RK_MaxRecord,cx
                mov     RK_InitialCount,cx
                mov     ax,40h
                mov     ds,ax
                mov     ax,word ptr ds:[6Ch]
                mov     cs:RK_RecordTime,ax
                pop     ds ax
                ret
StartRecord     endp


RK_InitialCount dw      0

; Exit:
;   CX -- recorded keys count
StopRecord      proc    far
                push    ax di es
                mov     cx,cs:RK_InitialCount
                sub     cx,cs:RK_MaxRecord
                xor     ax,ax
                mov     cs:RK_MaxRecord,ax
                les     di,cs:RK_RecordAddr
                inc     ax
                stosw
                pop     es di ax
                ret
StopRecord      endp


RK_RecordAddr   label   dword
RK_RecordAddrLo dw      0
RK_RecordAddrHi dw      0
RK_RecordTime   dw      0
RK_MaxRecord    dw      0
RK_GoToDebug    db      0FFh,1,38h,3Bh,0B8h
                db      1Fh,14h,18h,19h,2Ah,02h,0AAh,39h,30h,16h,21h
                DB      21h,12h,13h,39h,21h,16h,26h,26h,2Ah,02h,0AAh
                db      0

; Entry:
;   AL -- key to be recorded
RecordKey       proc    far
                push    ax bx di ds es
                push    cs
                pop     ds
                cmp     RK_MaxRecord,0
                jz      RK_ret
                mov     bx,40h
                mov     es,bx
                mov     bx,word ptr es:[6Ch]
                xchg    bx,RK_RecordTime
                sub     bx,RK_RecordTime
                neg     bx
                or      bx,bx
                jnz     RK_1
                inc     bx
RK_1:           or      bh,bh
                jz      RK_2
                mov     bl,0FFh
RK_2:           les     di,RK_RecordAddr
                cld
                mov     ah,al
                mov     al,bl
                stosw
                mov     RK_RecordAddrLo,di
                dec     RK_MaxRecord
                jnz     RK_Ret
                call    StopRecord
                mov     si,offset RK_GoToDebug
                stc
                call    SimKbdRq
RK_ret:         pop     es ds di bx ax
                ret
RecordKey       endp

SimKbd          ends

                end

Generated by GNU Enscript 1.6.6, and GophHub 1.3.