151 lines
No EOL
2.1 KiB
NASM
151 lines
No EOL
2.1 KiB
NASM
KEYBOARD_INTERRUPT equ 1 + 8
|
|
|
|
section data
|
|
key_codes:
|
|
.left dw 0xe04b
|
|
.right dw 0xe04d
|
|
.up dw 0xe048
|
|
.down dw 0xe050
|
|
|
|
; Non-hold codes
|
|
.turbo dw 0x0f ; tab
|
|
.exit dw 0x10 ; q
|
|
|
|
key_held:
|
|
.left db 0
|
|
.right db 0
|
|
.up db 0
|
|
.down db 0
|
|
.END:
|
|
section code
|
|
|
|
keyboard_init:
|
|
pusha
|
|
push ds
|
|
push es
|
|
mov ah, 0x35
|
|
mov al, KEYBOARD_INTERRUPT
|
|
int 0x21
|
|
|
|
push cs
|
|
pop ds
|
|
mov [.saved_handler], bx
|
|
mov ax, es
|
|
mov [.saved_handler + 2], ax
|
|
|
|
mov ah, 0x25
|
|
mov al, KEYBOARD_INTERRUPT
|
|
; ds is already set from earlier
|
|
mov dx, keyboard_irq
|
|
int 0x21
|
|
pop es
|
|
pop ds
|
|
popa
|
|
ret
|
|
|
|
section data
|
|
.saved_handler resw 2
|
|
section code
|
|
|
|
keyboard_deinit:
|
|
pusha
|
|
push ds
|
|
mov dx, [cs:keyboard_init.saved_handler]
|
|
mov ax, [cs:keyboard_init.saved_handler + 2]
|
|
mov ds, ax
|
|
mov ah, 0x25
|
|
mov al, KEYBOARD_INTERRUPT
|
|
int 0x21
|
|
pop ds
|
|
popa
|
|
ret
|
|
|
|
keyboard_irq:
|
|
pusha
|
|
; Get the byte from the keyboard controller
|
|
in al, 0x60
|
|
|
|
mov ah, [cs:.previous]
|
|
cmp ah, 0xe0
|
|
je .extended_key
|
|
xor ah, ah ; Zero out high byte, since it's not the extended prefix
|
|
.extended_key:
|
|
|
|
cmp ax, [cs:key_codes.turbo]
|
|
jne .no_turbo
|
|
not [cs:turbo]
|
|
.no_turbo:
|
|
|
|
call update_keys
|
|
|
|
cmp al, 0xe0
|
|
je .extended_prefix
|
|
mov [cs:read_key.key], ax
|
|
.extended_prefix:
|
|
|
|
mov [cs:.previous], al
|
|
|
|
; Acknowledge the receipt of the byte with the keyboard controller
|
|
in al, 0x61
|
|
mov ah, al
|
|
or al, 0x80
|
|
out 0x61, al
|
|
mov al, ah
|
|
out 0x61, al
|
|
|
|
; Acknowledge the handling of the interrupt with the PIC
|
|
mov al, 0x20
|
|
out 0x20, al
|
|
popa
|
|
iret
|
|
|
|
section data
|
|
.previous db 0
|
|
section code
|
|
|
|
; keycode -> ax
|
|
; new key available -> carry
|
|
read_key:
|
|
mov ax, [.key]
|
|
cmp ax, [.previous]
|
|
jne .new_key
|
|
clc
|
|
ret
|
|
.new_key:
|
|
mov [.previous], ax
|
|
stc
|
|
ret
|
|
|
|
section data
|
|
.key dw 0
|
|
.previous dw 0
|
|
section code
|
|
|
|
; ax = keycode
|
|
update_keys:
|
|
pusha
|
|
mov bx, ax
|
|
and bx, 0x80
|
|
jnz .key_up
|
|
mov bl, 1
|
|
jmp .mask_keycode
|
|
.key_up:
|
|
mov bl, 0
|
|
.mask_keycode:
|
|
and ax, 0xff7f
|
|
; ax = bare keycode, bl = keyup/keydown
|
|
|
|
mov cx, key_held.END - key_held
|
|
mov si, key_codes
|
|
mov di, key_held
|
|
.loop:
|
|
cmp ax, [cs:si]
|
|
jne .not_match
|
|
mov [cs:di], bl
|
|
.not_match:
|
|
add si, 2
|
|
inc di
|
|
loop .loop
|
|
|
|
popa
|
|
ret |