I am coding a game in assembly 8086. I fixed the issue when the game didn't open, but I can't fix the controls.
The ESC key works. When I press it, it goes to _QUIT function, but if any other key was pressed before that, the controls freeze and don't react on any key.
Is there something wrong with my function?
I tried to change the AL
register to AH
, but it didn't work.
_KEYCHECK:
mov ah,01h
int 16h
cmp al,1Bh ;ESC
je _QUIT
cmp al,48h ;UP
je _PLAYER.UP
cmp al,50h ;DOWN
je _PLAYER.DOWN
cmp al,4Bh ;LEFT
je _PLAYER.LEFT
cmp al,4Dh ;RIGHT
je _PLAYER.RIGHT
ret
Your _KEYCHECK function is using the BIOS.ReadKeyboardStatus function.
It will inform you about the availability of a keyboard key by setting the ZeroFlag (ZF) if no key is available, or by clearing the ZeroFlag if a key is waiting. In the latter case you will also receive the key's ASCII code and scancode.
The important thing here is that a key that is reported available stays in the keyboard buffer. The info that you get in AL
and AH
is just a preview not the actual key (in a sense). This explains your observation:
... but if any other key was pressed before that the controls frees ...
The solution is to remove the key from the keyboard buffer. That's what BIOS.ReadKeyboardCharacter does. If a key is waiting it will return very quickly with the key removed from the buffer. If no key is available it will wait until one comes available and then return with that key removed from the buffer.
_KEYCHECK:
mov ah, 01h ; BIOS.ReadKeyboardStatus
int 16h ; -> AX ZF
jz NoKeyAvailable
mov ah, 00h ; BIOS.ReadKeyboardCharacter
int 16h ; -> AX
cmp al, 1Bh ;ESC
je _QUIT
cmp ah, 48h ;UP
je _PLAYER.UP
cmp ah, 50h ;DOWN
je _PLAYER.DOWN
cmp ah, 4Bh ;LEFT
je _PLAYER.LEFT
cmp ah, 4Dh ;RIGHT
je _PLAYER.RIGHT
NoKeyAvailable:
ret
Please note:
AL
and AH
was valid.AL
but all the other codes 48h (UP), 50h (DOWN), 4Bh (LEFT), and 4Dh (RIGHT) are scancodes and thus have to be checked from AH
.