#define BUF_SZ 32
+#ifdef WANT_VARIADIC_VOIDP_CAST
+#define VOIDP(__x__) ((void *)(__x__))
+#else
+#define VOIDP(__x__) (__x__)
+#endif
+
static dcpu16_hw_signal_t keyboard_reset_;
static dcpu16_hw_signal_t keyboard_cycle_;
static dcpu16_hw_signal_t keyboard_hwi_;
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];
};
keysym_rfbtodcpu(key, &dcpu_key);
- fprintf(stderr, "%s: down:%u key:0x%04x dcpu_key:0x%04x\n", __func__,
- down, key, dcpu_key);
+ fprintf(stderr, "%s: down:%u key:0x%04x dcpu_key:0x%04x\n",
+ __func__,
+ down,
+ key,
+ dcpu_key);
- fprintf(stderr, "%s: hw:%p name:%s vm:%p\n", __func__, hw, hw->name_, hw->vm);
+ fprintf(stderr, "%s: hw:%p name:%s vm:%p\n",
+ __func__,
+ VOIDP(hw),
+ hw->name_,
+ VOIDP(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);
}
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 */
void keyboard_del(struct dcpu16_hw **hw) {
if (hw) {
- free(((struct keyboard_ *)((*hw)->data))->buf);
- ((struct keyboard_ *)((*hw)->data))->buf = NULL;
+ if (*hw) {
+ if ((*hw)->data) {
+ free(((struct keyboard_ *)((*hw)->data))->buf);
+ ((struct keyboard_ *)((*hw)->data))->buf = NULL;
- free((*hw)->data);
- (*hw)->data = NULL;
-
- free(*hw);
- *hw = NULL;
+ free((*hw)->data);
+ (*hw)->data = NULL;
+ }
+ free(*hw);
+ *hw = NULL;
+ }
}
}