fixed bug with instruction decoding in dcpu, fixed bugs in display
[dcpu16] / hw_keyboard.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4
5 #include "dcpu16.h"
6 #include "hw_keyboard.h"
7
8 #define BUF_SZ 32
9
10 static dcpu16_hw_signal_t keyboard_reset_;
11 static dcpu16_hw_signal_t keyboard_cycle_;
12 static dcpu16_hw_signal_t keyboard_hwi_;
13 static struct dcpu16_hw hw_ = {
14 .name_ = "Generic Keyboard (compatible)",
15 .id_l = 0x7406,
16 .id_h = 0x30cf,
17 .ver = 0x0001,
18 .mfg_l = 0x0000,
19 .mfg_h = 0x0000,
20 .hwi = keyboard_hwi_,
21 .cycle = keyboard_cycle_,
22 .reset = keyboard_reset_,
23 .data = (struct keyboard_ *)NULL
24 };
25
26 struct keyboard_ {
27 char *buf;
28 size_t buf_sz;
29 DCPU16_WORD interrupt_message;
30 };
31
32 static
33 void keyboard_reset_(struct dcpu16 *vm, void *data) {
34 struct keyboard_ *keyboard = (struct keyboard_ *)data;
35
36 (void)vm;
37
38 keyboard->interrupt_message = 0;
39 memset(keyboard->buf, 0, keyboard->buf_sz);
40 }
41
42 static
43 void keyboard_cycle_(struct dcpu16 *vm, void *data) {
44 struct keyboard_ *keyboard = (struct keyboard_ *)data;
45
46 (void)vm, (void)keyboard;
47 }
48
49 static
50 void keyboard_hwi_(struct dcpu16 *vm, void *data) {
51 struct keyboard_ *keyboard = (struct keyboard_ *)data;
52 DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A];
53 DCPU16_WORD reg_b = vm->reg[DCPU16_REG_B];
54 size_t i;
55
56 switch (reg_a) {
57 case 0: /* clear keyboard buffer */
58 memset(keyboard->buf, 0, keyboard->buf_sz);
59 break;
60
61 case 1: /* get next key from buffer as C */
62 vm->reg[DCPU16_REG_C] = keyboard->buf[0];
63 for (i = 1; i < keyboard->buf_sz; i++) {
64 keyboard->buf[i-1] = keyboard->buf[i];
65 }
66 keyboard->buf[i] = '\0';
67 break;
68
69 case 2: /* get currently-pressed-state of key in B as C */
70 vm->warn_cb_("IMPLEMENT");
71 (void)reg_b;
72 vm->reg[DCPU16_REG_C] = 0;
73 break;
74
75 case 3: /* set interrupt state */
76 keyboard->interrupt_message = reg_b;
77 break;
78
79 }
80 }
81
82 struct dcpu16_hw *keyboard_new(struct dcpu16 *vm) {
83 struct dcpu16_hw *hw;
84 char *b;
85
86 hw = calloc(1, sizeof *hw);
87 if (hw == NULL) {
88 vm->warn_cb_("%s():%s", "calloc", strerror(errno));
89 return NULL;
90 }
91 memcpy(hw, &hw_, sizeof *hw);
92 hw->data = calloc(1, sizeof hw->data);
93 if (hw->data == NULL) {
94 vm->warn_cb_("%s():%s", "calloc", strerror(errno));
95 free(hw);
96 return NULL;
97 }
98
99 b = calloc(BUF_SZ, sizeof *b);
100 if (b == NULL) {
101 vm->warn_cb_("%s():%s", "calloc", strerror(errno));
102 free(hw->data);
103 free(hw);
104 return NULL;
105 }
106 ((struct keyboard_ *)(hw->data))->buf = b;
107 ((struct keyboard_ *)(hw->data))->buf_sz = BUF_SZ;
108
109 return hw;
110 }
111
112 void keyboard_del(struct dcpu16_hw **hw) {
113 if (hw) {
114 free(((struct keyboard_ *)((*hw)->data))->buf);
115 ((struct keyboard_ *)((*hw)->data))->buf = NULL;
116
117 free((*hw)->data);
118 (*hw)->data = NULL;
119
120 free(*hw);
121 *hw = NULL;
122 }
123 }