I\'m working on an assignment for the univesity, we need to create a simple breakout/arkanoid clone, it is going pretty well but I found a bug that would delete everything o
You modify cx
in your keyboard interrupt without preserving it.
^^^ this is the ANSWER (what is causing your bug), not just some advice
Here some advice is following:
Also it feels wrong to have any loop (dynamic delay) in interrupt, interrupts should proceed as fast as possible.
I can't recall from head what is correct way to read 0x6X ports of keyboard (I just recall it is a bit tricky, to have it fully correct), so I'm not going to check particular in/out
sequence and its correctness.
But if you will set XXXpressed
in interrupt by actual current state, and the main loop will be too slow, it may not see very short key presses (as the input is not buffered). For a simple game as arkanoid clone this is OK, and I wouldn't be bothered by this at all, sounds to me as correct behaviour (you would need to be actually incredibly fast to hold the key so short).
Also you can avoid ds
setup in interrupt by reserving some data space near the interrupt code handler (moving escpressed dw 0
into the code part after iret
), then using that everywhere as mov word [cs:escpressed], 1
, etc. The total penalty for using cs:
addressing inside interrupt would be lower than the ds
setup, if you would actually set the memory flags in more efficient manner and short interrupt code (can be simplified a lot).
And it's sort of funny how extensively you use slow loop instruction for all main loops, but then in delay
subroutine you do the faster dec cx
jnz ...
alternative.
And I did check in the end how to write DOS keyboard handler, so this is my suggestion (unfortunately I didn't test it, if it works):
segment mycode code
escpressed db 0
leftpressed db 0
rightpressed db 0
KeybInt:
cli
push ax ;guardamos ax
; when IRQ1 is fired, int 9 is called to handle it and the input
; already waits on port 0x60, no need to validate IBF flag on 0x64
in al,60h ;obtenemos el codigo make o break de la tecla leida
mov ah,al
and al,0x7F ; AL = scan code without pressed/released flag
shr ah,7
xor ah,1 ; AH = 1/0 pressed/released
cmp al, 01h ;revisamos si es escape
jne .checkLeft
mov [cs:escpressed], ah
jmp .kbread
.checkLeft:
cmp al, 4bh ;revisamos si es la flecha izquierda
jne .checkRight
mov [cs:leftpressed], ah
jmp .kbread
.checkRight:
cmp al, 4dh ;revisamos si es la flecha derecha
jne .kbread
mov [cs:rightpressed], ah
.kbread:
in al, 61h
mov ah, al ; store original value
or al, 10000000b
out 61h, al ; set "enable kbd" bit
mov al, ah
out 61h, al ; set original value back
mov al, 20h
out 20h, al ; send end-of-interrupt signal to 8259 IC
pop ax ;recuperamos ax
sti ; not needed in real x86 real mode, IRET restores flags
iret ; but explicit STI paired with CLI may help some VMs
... then in game code, to check state of key, you must use cs
too:
...
cmp byte [cs:escpressed], 1
...