--- /dev/null
+#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;
+ }
+}