Koorosh
Koorosh

Reputation: 301

How to get realtime key presses in Assembly?

I have a simple EXE code written in emu8086 which moves a single character in screen (for now):

Preview

That yellow "*" moves with arrow keys.

The problem is emulator getting 16 key presses. I mean when I press keys so fast (Or hold a key), it will hold the key presses in a stack and moves the "*" based on them. For example:

Assembly Key presses

In picture above, the "*" moves 14 times based on keys I pressed before!

I don't want it to hold my key presses in a stack. How can I have a real-time reaction based on last key pressed and not a stack?

P.S.: Here's the part that I get key press from user, print an empty character at current location and moves the "*" to new location:

check_for_key:
    ; === check for player commands:
    mov     ah, 01h
    int     16h
    jz      no_key

    mov     ah, 00h
    int     16h

    mov     cur_dir, ah

    ; print ' ' at the location:
    mov     al, ' '
    mov     ah, 09h
    mov     bl, 0eh ; attribute.
    mov     cx, 1   ; single char.
    int     10h

    call    move_star

Upvotes: 3

Views: 6632

Answers (1)

mirabilos
mirabilos

Reputation: 5317

The BIOS always handles keyboard input in a buffer. You can circumvent that by installing your own interrupt handler, but that’s probably overkill.

You could also ensure your routine is faster than the key repeat delay.

But as a quick fix, you can change your input check like this:

check_for_key:
    ; === check for player commands:
    mov     ah, 01h
    int     16h
    jz      no_key

check_for_more_keys:
    mov     ah, 00h
    int     16h

    push    ax
    mov     ah, 01h
    int     16h
    jz      no_more_keys
    pop     ax
    jmp     check_for_more_keys

no_more_keys:
    pop     ax

    mov     cur_dir, ah

This makes your code read the entire buffer each time it wants a key, so it, in effect, only acts on the last key that was input when it checks for a key.

Upvotes: 6

Related Questions