f07489578b1157e80842a8ac0d7027761395ed99
[dcpu16] / hw_spc2000.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4
5 #include "dcpu16.h"
6 #include "hw_spc2000.h"
7
8 struct spc2000_ {
9 DCPU16_WORD skip_unit;
10 long long skip;
11 };
12
13 static
14 int spc2000_data_init_(struct dcpu16_hw *hw, void *data) {
15 (void)data;
16
17 hw->data = calloc(1, sizeof(struct spc2000_));
18 if (hw->data == NULL) {
19 hw->vm->warn_cb_("%s():%s", "calloc", strerror(errno));
20 return -1;
21 }
22 return 0;
23 }
24
25 static
26 void spc2000_data_free_(struct dcpu16_hw *hw) {
27 if (hw) {
28 if (hw->data) {
29 free(hw->data);
30 hw->data = NULL;
31 }
32 }
33 }
34
35 static
36 void spc2000_reset_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
37 struct spc2000_ *spc2000 = (struct spc2000_ *)hw->data;
38
39 (void)vm;
40
41 memset(spc2000, 0, sizeof *spc2000);
42 }
43
44 static
45 void spc2000_cycle_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
46 struct spc2000_ *spc2000 = (struct spc2000_ *)hw->data;
47
48 (void)vm;
49 (void)spc2000;
50 }
51
52 static
53 void spc2000_hwi_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
54 struct spc2000_ *spc2000 = (struct spc2000_ *)hw->data;
55 DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A],
56 reg_b = vm->reg[DCPU16_REG_B];
57 long long x;
58
59 switch (reg_a) {
60 case 0: /* GET_STATUS */
61 case 2: /* TRIGGER_DEVICE */
62 /* check status */
63 vm->reg[DCPU16_REG_C] = 0;
64 vm->reg[DCPU16_REG_B] = 0;
65 if (reg_a == 0
66 || vm->reg[DCPU16_REG_C] != 0)
67 break;
68 /* trigger */
69 vm->warn_cb_("spc2000 triggered\n");
70 break;
71
72 case 1: /* SET_UNIT_TO_SKIP */
73 spc2000->skip = vm->ram[reg_b];
74 x = vm->ram[reg_b + 1];
75 spc2000->skip |= x << 16;
76 x = vm->ram[reg_b + 2];
77 spc2000->skip |= x << 32;
78 x = vm->ram[reg_b + 3];
79 spc2000->skip |= x << 48;
80 break;
81
82 case 3: /* SET_SKIP_UNIT */
83 spc2000->skip_unit = reg_b;
84 break;
85 }
86 }
87
88 static struct dcpu16_hw hw_ = {
89 .vm = NULL,
90 .name_ = "SPC2000 - Suspension Chamber 2000",
91 .id_l = 0x1d9d,
92 .id_h = 0x40e4,
93 .ver = 0x005e,
94 .mfg_l = 0x8b36,
95 .mfg_h = 0x1c6c,
96 .hwi = spc2000_hwi_,
97 .cycle = spc2000_cycle_,
98 .reset = spc2000_reset_,
99 .data = (struct spc2000_ *)NULL
100 };
101
102 struct dcpu16_hw_module dcpu16_hw_module_spc2000 = {
103 .template = &hw_,
104 .data_init = spc2000_data_init_,
105 .data_free = spc2000_data_free_,
106 };