taytyypa-menna-nopeasti/keyboard.asm
Juhani Krekelä 11f90d01bf Collision
2025-10-26 00:35:46 +03:00

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