stop appending repeat keys to the input buffer
[retroray] / src / dos / keyb.c
index e35cb7b..8789ea7 100644 (file)
@@ -1,6 +1,6 @@
 /*
 DOS interrupt-based keyboard driver.
-Copyright (C) 2013  John Tsiombikas <nuclear@member.fsf.org>
+Copyright (C) 2013-2023  John Tsiombikas <nuclear@member.fsf.org>
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -35,11 +35,11 @@ along with the program. If not, see <http://www.gnu.org/licenses/>
 
 #include "keyb.h"
 #include "scancode.h"
-#include "inttypes.h"
+#include "sizeint.h"
 #include "dosutil.h"
 
-#define KB_INTR                0x9
-#define KB_PORT                0x60
+#define KEY_INTR               0x9
+#define KEY_PORT               0x60
 
 #define PIC1_CMD_PORT  0x20
 #define OCW2_EOI               (1 << 5)
@@ -60,27 +60,23 @@ static _go32_dpmi_seginfo intr, prev_intr;
 
 static void INTERRUPT kbintr();
 
-static int *buffer;
-static int buffer_size, buf_ridx, buf_widx;
+#define BUFSIZE                64
+static int buffer[BUFSIZE];
+static int buf_ridx, buf_widx;
 static int last_key;
 
 static unsigned int num_pressed;
-static unsigned char keystate[256];
+static unsigned char keystate[512];
 
-#define ADVANCE(x)     ((x) = ((x) + 1) % buffer_size)
+#define ADVANCE(x)     ((x) = ((x) + 1) & (BUFSIZE - 1))
 
-int kb_init(int bufsz)
+void kb_init(void)
 {
        if(DONE_INIT) {
-               fprintf(stderr, "keyboard driver already initialized!\n");
-               return 0;
+               errormsg("keyboard driver already initialized!\n");
+               return;
        }
 
-       buffer_size = bufsz;
-       if(buffer_size && !(buffer = malloc(buffer_size * sizeof *buffer))) {
-               fprintf(stderr, "failed to allocate input buffer, continuing without\n");
-               buffer_size = 0;
-       }
        buf_ridx = buf_widx = 0;
        last_key = -1;
 
@@ -90,19 +86,17 @@ int kb_init(int bufsz)
        /* set our interrupt handler */
        _disable();
 #ifdef __WATCOMC__
-       prev_handler = _dos_getvect(KB_INTR);
-       _dos_setvect(KB_INTR, kbintr);
+       prev_handler = _dos_getvect(KEY_INTR);
+       _dos_setvect(KEY_INTR, kbintr);
 #endif
 #ifdef __DJGPP__
-       _go32_dpmi_get_protected_mode_interrupt_vector(KB_INTR, &prev_intr);
+       _go32_dpmi_get_protected_mode_interrupt_vector(KEY_INTR, &prev_intr);
        intr.pm_offset = (intptr_t)kbintr;
        intr.pm_selector = _go32_my_cs();
        _go32_dpmi_allocate_iret_wrapper(&intr);
-       _go32_dpmi_set_protected_mode_interrupt_vector(KB_INTR, &intr);
+       _go32_dpmi_set_protected_mode_interrupt_vector(KEY_INTR, &intr);
 #endif
        _enable();
-
-       return 0;
 }
 
 void kb_shutdown(void)
@@ -114,28 +108,29 @@ void kb_shutdown(void)
        /* restore the original interrupt handler */
        _disable();
 #ifdef __WATCOMC__
-       _dos_setvect(KB_INTR, prev_handler);
+       _dos_setvect(KEY_INTR, prev_handler);
 #endif
 #ifdef __DJGPP__
-       _go32_dpmi_set_protected_mode_interrupt_vector(KB_INTR, &prev_intr);
+       _go32_dpmi_set_protected_mode_interrupt_vector(KEY_INTR, &prev_intr);
        _go32_dpmi_free_iret_wrapper(&intr);
 #endif
        _enable();
-
-       free(buffer);
 }
 
 int kb_isdown(int key)
 {
        switch(key) {
-       case KB_ANY:
+       case KEY_ANY:
                return num_pressed;
 
-       case KB_ALT:
-               return keystate[KB_LALT] + keystate[KB_RALT];
+       case KEY_ALT:
+               return keystate[KEY_LALT] + keystate[KEY_RALT];
 
-       case KB_CTRL:
-               return keystate[KB_LCTRL] + keystate[KB_RCTRL];
+       case KEY_CTRL:
+               return keystate[KEY_LCTRL] + keystate[KEY_RCTRL];
+
+       case KEY_SHIFT:
+               return keystate[KEY_LSHIFT] + keystate[KEY_RSHIFT];
        }
 
        if(isalpha(key)) {
@@ -191,7 +186,7 @@ void kb_putback(int key)
        if(buffer) {
                /* go back a place */
                if(--buf_ridx < 0) {
-                       buf_ridx += buffer_size;
+                       buf_ridx += BUFSIZE;
                }
 
                /* if the write end hasn't caught up with us, go back one place
@@ -214,7 +209,7 @@ static void INTERRUPT kbintr()
        int key, c, press;
        static int ext;
 
-       code = inp(KB_PORT);
+       code = inp(KEY_PORT);
 
        if(code == 0xe0) {
                ext = 1;
@@ -240,21 +235,19 @@ static void INTERRUPT kbintr()
                ext = 0;
        } else {
                key = scantbl[code];
-               c = (keystate[KB_LSHIFT] | keystate[KB_RSHIFT]) ? scantbl_shift[code] : key;
+               c = (keystate[KEY_LSHIFT] | keystate[KEY_RSHIFT]) ? scantbl_shift[code] : key;
        }
 
-       if(press) {
+       if(press && !keystate[key]) {
                /* append to buffer */
                last_key = c;
-               if(buffer_size > 0) {
-                       buffer[buf_widx] = c;
-                       ADVANCE(buf_widx);
-                       /* if the write end overtook the read end, advance the read end
-                        * too, to discard the oldest keypress from the buffer
-                        */
-                       if(buf_widx == buf_ridx) {
-                               ADVANCE(buf_ridx);
-                       }
+               buffer[buf_widx] = c;
+               ADVANCE(buf_widx);
+               /* if the write end overtook the read end, advance the read end
+                * too, to discard the oldest keypress from the buffer
+                */
+               if(buf_widx == buf_ridx) {
+                       ADVANCE(buf_ridx);
                }
        }