actually use ring buffer in hw_keyboard.c
authorJustin Wind <justin.wind@gmail.com>
Wed, 16 May 2012 05:07:28 +0000 (22:07 -0700)
committerJustin Wind <justin.wind@gmail.com>
Wed, 16 May 2012 05:07:28 +0000 (22:07 -0700)
hw_keyboard.c

index 28d66d63c6c0f16a14cdfe57403a104ecd170ca4..d5c90b3faf4b2af6f5a1519894c02107d8b7ea8d 100644 (file)
@@ -32,6 +32,8 @@ static struct dcpu16_hw hw_ = {
 struct keyboard_ {
     char *buf;
     size_t buf_sz;
+    size_t buf_head;
+    size_t buf_tail;
     DCPU16_WORD interrupt_message;
     unsigned char keys_pressed[256];
 };
@@ -87,8 +89,15 @@ void keyboard_rfbevent_(rfbBool down, rfbKeySym key, rfbClientPtr cl) {
     fprintf(stderr, "%s: hw:%p name:%s vm:%p\n", __func__, hw, hw->name_, hw->vm);
 
     keyboard->keys_pressed[dcpu_key] = (down ? 1 : 0);
-    if (down)
-        keyboard->buf[0] = dcpu_key;
+    if (down) {
+        if ((keyboard->buf_tail + 1) % keyboard->buf_sz == keyboard->buf_head) {
+            hw->vm->warn_cb_("keyboard buffer overflow");
+            return;
+        }
+        keyboard->buf[keyboard->buf_tail] = dcpu_key;
+        keyboard->buf_tail += 1;
+        keyboard->buf_tail %= keyboard->buf_sz;
+    }
     if (keyboard->interrupt_message) {
         dcpu16_interrupt(hw->vm, keyboard->interrupt_message);
     }
@@ -122,19 +131,20 @@ void keyboard_hwi_(struct dcpu16 *vm, void *data) {
     struct keyboard_ *keyboard = (struct keyboard_ *)data;
     DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A];
     DCPU16_WORD reg_b = vm->reg[DCPU16_REG_B];
-    size_t i;
 
     switch (reg_a) {
         case 0: /* clear keyboard buffer */
             memset(keyboard->buf, 0, keyboard->buf_sz);
+            keyboard->buf_head = 0;
+            keyboard->buf_tail = 0;
             break;
 
         case 1: /* get next key from buffer as C */
-            vm->reg[DCPU16_REG_C] = keyboard->buf[0];
-            for (i = 1; i < keyboard->buf_sz; i++) {
-                keyboard->buf[i-1] = keyboard->buf[i];
-            }
-            keyboard->buf[i] = '\0';
+            if (keyboard->buf_head == keyboard->buf_tail)
+                break;
+            vm->reg[DCPU16_REG_C] = keyboard->buf[keyboard->buf_head];
+            keyboard->buf_head += 1;
+            keyboard->buf_head %= keyboard->buf_sz;
             break;
 
         case 2: /* get currently-pressed-state of key in B as C */