X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=hw_keyboard.c;fp=hw_keyboard.c;h=71e016f652e2e6acf703077e3357b3b6009c6380;hb=0a1b4588f79e3719af9431a98da44350030df754;hp=0000000000000000000000000000000000000000;hpb=b819e4d8f696703ad42c97b357672fd9325bdac6;p=dcpu16 diff --git a/hw_keyboard.c b/hw_keyboard.c new file mode 100644 index 0000000..71e016f --- /dev/null +++ b/hw_keyboard.c @@ -0,0 +1,123 @@ +#include +#include +#include + +#include "dcpu16.h" +#include "hw_keyboard.h" + +#define BUF_SZ 32 + +static dcpu16_hw_signal_t keyboard_reset_; +static dcpu16_hw_signal_t keyboard_cycle_; +static dcpu16_hw_signal_t keyboard_hwi_; +static struct dcpu16_hw hw_ = { + .name_ = "Generic Keyboard (compatible)", + .id_l = 0x7406, + .id_h = 0x30cf, + .ver = 0x0001, + .mfg_l = 0x0000, + .mfg_h = 0x0000, + .hwi = keyboard_hwi_, + .cycle = keyboard_cycle_, + .reset = keyboard_reset_, + .data = (struct keyboard_ *)NULL +}; + +struct keyboard_ { + char *buf; + size_t buf_sz; + DCPU16_WORD interrupt_message; +}; + +static +void keyboard_reset_(struct dcpu16 *vm, void *data) { + struct keyboard_ *keyboard = (struct keyboard_ *)data; + + (void)vm; + + keyboard->interrupt_message = 0; + memset(keyboard->buf, 0, keyboard->buf_sz); +} + +static +void keyboard_cycle_(struct dcpu16 *vm, void *data) { + struct keyboard_ *keyboard = (struct keyboard_ *)data; + + (void)vm, (void)keyboard; +} + +static +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); + 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'; + break; + + case 2: /* get currently-pressed-state of key in B as C */ + vm->warn_cb_("IMPLEMENT"); + (void)reg_b; + vm->reg[DCPU16_REG_C] = 0; + break; + + case 3: /* set interrupt state */ + keyboard->interrupt_message = reg_b; + break; + + } +} + +struct dcpu16_hw *keyboard_new(struct dcpu16 *vm) { + struct dcpu16_hw *hw; + char *b; + + hw = calloc(1, sizeof *hw); + if (hw == NULL) { + vm->warn_cb_("%s():%s", "calloc", strerror(errno)); + return NULL; + } + memcpy(hw, &hw_, sizeof *hw); + hw->data = calloc(1, sizeof hw->data); + if (hw->data == NULL) { + vm->warn_cb_("%s():%s", "calloc", strerror(errno)); + free(hw); + return NULL; + } + + b = calloc(BUF_SZ, sizeof *b); + if (b == NULL) { + vm->warn_cb_("%s():%s", "calloc", strerror(errno)); + free(hw->data); + free(hw); + return NULL; + } + ((struct keyboard_ *)(hw->data))->buf = b; + ((struct keyboard_ *)(hw->data))->buf_sz = BUF_SZ; + + return hw; +} + +void keyboard_del(struct dcpu16_hw **hw) { + if (hw) { + free(((struct keyboard_ *)((*hw)->data))->buf); + ((struct keyboard_ *)((*hw)->data))->buf = NULL; + + free((*hw)->data); + (*hw)->data = NULL; + + free(*hw); + *hw = NULL; + } +}