added doc files, test for display
[dcpu16] / hw_spc2000.c
diff --git a/hw_spc2000.c b/hw_spc2000.c
new file mode 100644 (file)
index 0000000..2fa0c7b
--- /dev/null
@@ -0,0 +1,80 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "dcpu16.h"
+#include "hw_spc2000.h"
+
+static dcpu16_hw_signal_t spc2000_reset_;
+static dcpu16_hw_signal_t spc2000_cycle_;
+static dcpu16_hw_signal_t spc2000_hwi_;
+static struct dcpu16_hw hw_ = {
+    .name_  = "SPC2000 - Suspension Chamber 2000",
+    .id_l   = 0x1d9d,
+    .id_h   = 0x40e4,
+    .ver    = 0x005e,
+    .mfg_l  = 0x8b36,
+    .mfg_h  = 0x1c6c,
+    .hwi    = spc2000_hwi_,
+    .cycle  = spc2000_cycle_,
+    .reset  = spc2000_reset_,
+    .data   = (struct spc2000_ *)NULL
+};
+
+struct spc2000_ {
+    DCPU16_WORD skip_unit;
+    long long skip;
+};
+
+static
+void spc2000_reset_(struct dcpu16 *vm, void *data) {
+    struct spc2000_ *spc2000 = (struct spc2000_ *)data;
+
+    (void)vm;
+
+    memset(spc2000, 0, sizeof *spc2000);
+}
+
+static
+void spc2000_cycle_(struct dcpu16 *vm, void *data) {
+    struct spc2000_ *spc2000 = (struct spc2000_ *)data;
+
+    (void)vm;
+    (void)spc2000;
+}
+
+static
+void spc2000_hwi_(struct dcpu16 *vm, void *data) {
+    struct spc2000_ *spc2000 = (struct spc2000_ *)data;
+    DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A],
+                reg_b = vm->reg[DCPU16_REG_B];
+    long long x;
+
+    switch (reg_a) {
+        case 0: /* GET_STATUS */
+        case 2: /* TRIGGER_DEVICE */
+            /* check status */
+            vm->reg[DCPU16_REG_C] = 0;
+            vm->reg[DCPU16_REG_B] = 0;
+            if (reg_a == 0
+            ||  vm->reg[DCPU16_REG_C] != 0)
+                break;
+            /* trigger */
+            vm->warn_cb_("spc2000 triggered\n");
+            break;
+
+        case 1: /* SET_UNIT_TO_SKIP */
+            spc2000->skip = vm->ram[reg_b];
+            x = vm->ram[reg_b + 1];
+            spc2000->skip |= x << 16;
+            x = vm->ram[reg_b + 2];
+            spc2000->skip |= x << 32;
+            x = vm->ram[reg_b + 3];
+            spc2000->skip |= x << 48;
+            break;
+
+        case 3: /* SET_SKIP_UNIT */
+            spc2000->skip_unit = reg_b;
+            break;
+    }
+}