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