modualarized 'hardware' api changes complete
authorJustin Wind <justin.wind@gmail.com>
Fri, 18 May 2012 00:53:24 +0000 (17:53 -0700)
committerJustin Wind <justin.wind@gmail.com>
Fri, 18 May 2012 00:53:24 +0000 (17:53 -0700)
dcpu16.c
dcpu16.h
hw_clock.c
hw_clock.h
hw_keyboard.c
hw_keyboard.h
hw_lem1802.c
hw_lem1802.h
hw_spc2000.c
vm-dcpu16.c

index 6ab689888d70a28587f07a47560adf1130d254cd..a0e1ad0ca3864ee2be54535b1f5030c79713a9a2 100644 (file)
--- a/dcpu16.c
+++ b/dcpu16.c
@@ -172,7 +172,7 @@ void dcpu16_cycle_inc(struct dcpu16 *vm, unsigned int n) {
         /* signal attached hardware */
         for (i = 0; i < vm->hw_table_entries_; i++) {
             TRACE("%s>> notifying %s", __func__, vm->hw_table_[i].name_);
-            vm->hw_table_[i].cycle(vm, vm->hw_table_[i].data);
+            vm->hw_table_[i].cycle(vm, &vm->hw_table_[i]);
         }
     }
 }
@@ -533,7 +533,7 @@ OP_IMPL(nbi_hwi) {
 
     dcpu16_cycle_inc(vm, 4);
     if (vm->hw_table_[*a].hwi)
-        vm->hw_table_[*a].hwi(vm, vm->hw_table_[*a].data);
+        vm->hw_table_[*a].hwi(vm, &vm->hw_table_[*a]);
     else
         WARN("hardware 0x%04x has no interrupt handler", *a);
 }
@@ -1396,7 +1396,7 @@ void dcpu16_hw_del(struct dcpu16_hw **hw) {
 /*  dcpu16_hw_add
  *  registers new 'hardware' device with system
  */
-int dcpu16_hw_add(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+int dcpu16_hw_attach(struct dcpu16 *vm, struct dcpu16_hw *hw) {
     if (!vm || !hw)
         return -1;
 
@@ -1485,7 +1485,7 @@ void dcpu16_reset(struct dcpu16 *vm) {
     /* signal attached hardware */
     for (i = 0; i < vm->hw_table_entries_; i++) {
         if (vm->hw_table_[i].reset) 
-            vm->hw_table_[i].reset(vm, vm->hw_table_[i].data);
+            vm->hw_table_[i].reset(vm, &vm->hw_table_[i]);
     }
 
     memset(vm->reg, 0, sizeof vm->reg);
index ebf20721051e11823f4113735d443a13541d56bd..9ca39124e402cfa8b5030a5e65513f54d1ecb7dc 100644 (file)
--- a/dcpu16.h
+++ b/dcpu16.h
@@ -67,7 +67,7 @@ struct dcpu16_acct_cb {
     dcpu16_acct_event mask;
 };
 
-typedef void (dcpu16_hw_signal_t)(struct dcpu16 *, void *);
+typedef void (dcpu16_hw_signal_t)(struct dcpu16 *, struct dcpu16_hw *);
 typedef void (dcpu16_hw_data_free_t)(struct dcpu16_hw *);
 /* these are used to define hardware attached to the system */
 struct dcpu16_hw {
@@ -113,8 +113,12 @@ DCPU16_WORD dcpu16_mnemonify_buf(DCPU16_WORD *);
 /* print the instruction at the specified address, returns number of words consumed in decoding */
 DCPU16_WORD dcpu16_disassemble_print(struct dcpu16 *, DCPU16_WORD);
 
+/* create and delete 'hardware' objects */
+struct dcpu16_hw *dcpu16_hw_new(struct dcpu16 *, struct dcpu16_hw_module *, void *);
+void dcpu16_hw_del(struct dcpu16_hw **);
+
 /* register new 'hardware' device with system */
-int dcpu16_hw_add(struct dcpu16 *, struct dcpu16_hw *);
+int dcpu16_hw_attach(struct dcpu16 *, struct dcpu16_hw *);
 
 /* register a callback for an accounting event */
 int dcpu16_acct_add(struct dcpu16 *, dcpu16_acct_event, dcpu16_ev_cb_t *, void *);
index 89d5912e0092132739f6d74a2fe3686a440f1f70..f70dcf4c3d368f634f12435d62ab5cd4ea2c1f37 100644 (file)
@@ -5,22 +5,6 @@
 #include "dcpu16.h"
 #include "hw_clock.h"
 
-static dcpu16_hw_signal_t clock_reset_;
-static dcpu16_hw_signal_t clock_cycle_;
-static dcpu16_hw_signal_t clock_hwi_;
-static struct dcpu16_hw hw_ = {
-    .name_  = "Generic Clock (compatible)",
-    .id_l   = 0xb402,
-    .id_h   = 0x12d0,
-    .ver    = 0x0001,
-    .mfg_l  = 0x0000,
-    .mfg_h  = 0x0000,
-    .hwi    = clock_hwi_,
-    .cycle  = clock_cycle_,
-    .reset  = clock_reset_,
-    .data   = (struct clock_ *)NULL
-};
-
 struct clock_ {
     DCPU16_WORD cycle_;
     DCPU16_WORD rate;
@@ -29,8 +13,8 @@ struct clock_ {
 };
 
 static
-void clock_reset_(struct dcpu16 *vm, void *data) {
-    struct clock_ *clock = (struct clock_ *)data;
+void clock_reset_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct clock_ *clock = (struct clock_ *)hw->data;
 
     (void)vm;
 
@@ -38,8 +22,8 @@ void clock_reset_(struct dcpu16 *vm, void *data) {
 }
 
 static
-void clock_cycle_(struct dcpu16 *vm, void *data) {
-    struct clock_ *clock = (struct clock_ *)data;
+void clock_cycle_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct clock_ *clock = (struct clock_ *)hw->data;
 
     /* cycle is only called 100000 times per second */
     /* maximum rate is 60hz / word_max = 3932160 */
@@ -55,14 +39,14 @@ void clock_cycle_(struct dcpu16 *vm, void *data) {
 
         if (clock->interrupt_message) {
             if (dcpu16_interrupt(vm, clock->interrupt_message))
-                vm->warn_cb_("%s: could not send interrupt", hw_.name_);
+                vm->warn_cb_("%s: could not send interrupt", hw->name_);
         }
     }
 }
 
 static
-void clock_hwi_(struct dcpu16 *vm, void *data) {
-    struct clock_ *clock = (struct clock_ *)data;
+void clock_hwi_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct clock_ *clock = (struct clock_ *)hw->data;
     DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A];
     DCPU16_WORD reg_b = vm->reg[DCPU16_REG_B];
 
@@ -81,32 +65,43 @@ void clock_hwi_(struct dcpu16 *vm, void *data) {
     }
 }
 
-/* instantitate a new clock */
-struct dcpu16_hw *clock_new(struct dcpu16 *vm) {
-    struct dcpu16_hw *hw;
+static
+int clock_data_init_(struct dcpu16_hw *hw, void *data) {
+    (void)data;
 
-    hw = calloc(1, sizeof *hw);
-    if (hw == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
-        return NULL;
-    }
-    memcpy(hw, &hw_, sizeof *hw);
-    hw->data = calloc(1, sizeof hw->data);
+    hw->data = calloc(1, sizeof(struct clock_));
     if (hw->data == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
-        free(hw);
-        return NULL;
+        hw->vm->warn_cb_("%s():%s", "calloc", strerror(errno));
+        return -1;
     }
-
-    return hw;
+    return 0;
 }
 
-void clock_del(struct dcpu16_hw **hw) {
+static
+void clock_data_free_(struct dcpu16_hw *hw) {
     if (hw) {
-        free((*hw)->data);
-        (*hw)->data = NULL;
-
-        free((*hw));
-        *hw = NULL;
+        if (hw->data) {
+            free(hw->data);
+            hw->data = NULL;
+        }
     }
 }
+
+static struct dcpu16_hw hw_ = {
+    .name_  = "Generic Clock (compatible)",
+    .id_l   = 0xb402,
+    .id_h   = 0x12d0,
+    .ver    = 0x0001,
+    .mfg_l  = 0x0000,
+    .mfg_h  = 0x0000,
+    .hwi    = clock_hwi_,
+    .cycle  = clock_cycle_,
+    .reset  = clock_reset_,
+    .data   = (struct clock_ *)NULL
+};
+
+struct dcpu16_hw_module dcpu16_hw_module_clock = {
+    .template = &hw_,
+    .data_init = clock_data_init_,
+    .data_free = clock_data_free_,
+};
index 263c03b68a0d5f03b880713e0ffd8d023218bb6c..edb773f9067f36d49068d2ded801a471ed0afaae 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef CLOCK_H_P5G2G9FA
 #define CLOCK_H_P5G2G9FA
 
-struct dcpu16_hw *clock_new(struct dcpu16 *);
-void clock_del(struct dcpu16_hw **);
+extern struct dcpu16_hw_module dcpu16_hw_module_clock;
 
 #endif /* CLOCK_H_P5G2G9FA */
index 90c30b3809590f9882a91da23f67a0af17d476c8..428971d5a6a6ecfcb51c0e19e88d3ed024c23ab6 100644 (file)
 #define VOIDP(__x__) (__x__)
 #endif
 
-static dcpu16_hw_signal_t keyboard_reset_;
-static dcpu16_hw_signal_t keyboard_cycle_;
-static dcpu16_hw_signal_t keyboard_hwi_;
-static struct dcpu16_hw hw_ = {
-    .vm     = NULL,
-    .name_  = "Generic Keyboard (compatible)",
-    .id_l   = 0x7406,
-    .id_h   = 0x30cf,
-    .ver    = 0x0001,
-    .mfg_l  = 0x0000,
-    .mfg_h  = 0x0000,
-    .hwi    = keyboard_hwi_,
-    .cycle  = keyboard_cycle_,
-    .reset  = keyboard_reset_,
-    .data   = (struct keyboard_ *)NULL
-};
-
 struct keyboard_ {
     char *buf;
     size_t buf_sz;
@@ -123,8 +106,8 @@ void keyboard_vnc_associate(struct dcpu16_hw *hw, rfbScreenInfoPtr rfbScreen) {
 #endif /* HAVE_LIBVNCSERVER */
 
 static
-void keyboard_reset_(struct dcpu16 *vm, void *data) {
-    struct keyboard_ *keyboard = (struct keyboard_ *)data;
+void keyboard_reset_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct keyboard_ *keyboard = (struct keyboard_ *)hw->data;
 
     (void)vm;
 
@@ -133,15 +116,15 @@ void keyboard_reset_(struct dcpu16 *vm, void *data) {
 }
 
 static
-void keyboard_cycle_(struct dcpu16 *vm, void *data) {
-    struct keyboard_ *keyboard = (struct keyboard_ *)data;
+void keyboard_cycle_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct keyboard_ *keyboard = (struct keyboard_ *)hw->data;
 
     (void)vm, (void)keyboard;
 }
 
 static
-void keyboard_hwi_(struct dcpu16 *vm, void *data) {
-    struct keyboard_ *keyboard = (struct keyboard_ *)data;
+void keyboard_hwi_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct keyboard_ *keyboard = (struct keyboard_ *)hw->data;
     DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A];
     DCPU16_WORD reg_b = vm->reg[DCPU16_REG_B];
 
@@ -171,50 +154,59 @@ void keyboard_hwi_(struct dcpu16 *vm, void *data) {
     }
 }
 
-struct dcpu16_hw *keyboard_new(struct dcpu16 *vm) {
-    struct dcpu16_hw *hw;
-    char *b;
+static
+int keyboard_data_init_(struct dcpu16_hw *hw, void *data) {
+    size_t buf_sz = data ? *(size_t *)data : BUF_SZ;
 
-    hw = calloc(1, sizeof *hw);
-    if (hw == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
-        return NULL;
-    }
-    memcpy(hw, &hw_, sizeof *hw);
-    hw->data = calloc(1, sizeof hw->data);
+    hw->data = calloc(1, sizeof(struct keyboard_));
     if (hw->data == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
-        free(hw);
-        return NULL;
+        hw->vm->warn_cb_("%s():%s", "calloc", strerror(errno));
+        return -1;
     }
 
-    b = calloc(BUF_SZ, sizeof *b);
-    if (b == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
+    ((struct keyboard_ *)(hw->data))->buf = malloc(buf_sz * sizeof *((struct keyboard_ *)(hw->data))->buf);
+    if (((struct keyboard_ *)(hw->data))->buf == NULL) {
+        hw->vm->warn_cb_("%s():%s", "malloc", strerror(errno));
         free(hw->data);
-        free(hw);
-        return NULL;
+        hw->data = NULL;
+        return -1;
     }
-    ((struct keyboard_ *)(hw->data))->buf = b;
-    ((struct keyboard_ *)(hw->data))->buf_sz = BUF_SZ;
 
-    hw->vm = vm;
+    ((struct keyboard_ *)(hw->data))->buf_sz = buf_sz;
 
-    return hw;
+    return 0;
 }
 
-void keyboard_del(struct dcpu16_hw **hw) {
+static
+void keyboard_data_free_(struct dcpu16_hw *hw) {
     if (hw) {
-        if (*hw) {
-            if ((*hw)->data) {
-                free(((struct keyboard_ *)((*hw)->data))->buf);
-                ((struct keyboard_ *)((*hw)->data))->buf = NULL;
-
-                free((*hw)->data);
-                (*hw)->data = NULL;
+        if (hw->data) {
+            if (((struct keyboard_ *)(hw->data))->buf) {
+                free(((struct keyboard_ *)(hw->data))->buf);
+                ((struct keyboard_ *)(hw->data))->buf = NULL;
             }
-            free(*hw);
-            *hw = NULL;
+            free(hw->data);
+            hw->data = NULL;
         }
     }
 }
+
+static struct dcpu16_hw hw_ = {
+    .vm     = NULL,
+    .name_  = "Generic Keyboard (compatible)",
+    .id_l   = 0x7406,
+    .id_h   = 0x30cf,
+    .ver    = 0x0001,
+    .mfg_l  = 0x0000,
+    .mfg_h  = 0x0000,
+    .hwi    = keyboard_hwi_,
+    .cycle  = keyboard_cycle_,
+    .reset  = keyboard_reset_,
+    .data   = (struct keyboard_ *)NULL
+};
+
+struct dcpu16_hw_module dcpu16_hw_module_keyboard = {
+    .template = &hw_,
+    .data_init = keyboard_data_init_,
+    .data_free = keyboard_data_free_,
+};
index a36047651b82f856394e338085fcc0993a91426b..bb44a93346e7026e615ff66fbf1e9b2a4cbed797 100644 (file)
@@ -7,8 +7,7 @@
 
 #include "dcpu16.h"
 
-struct dcpu16_hw *keyboard_new(struct dcpu16 *);
-void keyboard_del(struct dcpu16_hw **);
+extern struct dcpu16_hw_module dcpu16_hw_module_keyboard;
 
 #ifdef HAVE_LIBVNCSERVER
 void keyboard_vnc_associate(struct dcpu16_hw *, rfbScreenInfoPtr);
index 31a69b8be3e8f6ffc5fccf0c5b8ce3ba6f1d9bc6..f17ebc73287a2eff7eaa083f37fb400e6bf3548c 100644 (file)
 #define VOIDFP(__x__) (__x__)
 #endif
 
-static dcpu16_hw_signal_t lem1802_reset_;
-static dcpu16_hw_signal_t lem1802_cycle_;
-static dcpu16_hw_signal_t lem1802_hwi_;
-static struct dcpu16_hw hw_ = {
-    .name_  = "LEM1802 - Low Energy Monitor",
-    .id_l   = 0xf615,
-    .id_h   = 0x7349,
-    .ver    = 0x1802,
-    .mfg_l  = 0x8b36,
-    .mfg_h  = 0x1c6c,
-    .hwi    = lem1802_hwi_,
-    .cycle  = lem1802_cycle_,
-    .reset  = lem1802_reset_,
-    .data   = (struct lem1802_ *)NULL
-};
-
 #define LEM1802_POWER_ON_CYCLES 100000 /* this should vary by, let us say, 10% */
 
 #define PIX_X 160       /* pixels in display */
@@ -383,8 +367,8 @@ int pixbuf_render_vnc_(void *data, struct pixel_ *pixbuf, size_t x, size_t y) {
 
 
 static
-void lem1802_reset_(struct dcpu16 *vm, void *data) {
-    struct lem1802_ *display = (struct lem1802_ *)data;
+void lem1802_reset_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct lem1802_ *display = (struct lem1802_ *)hw->data;
 
     (void)vm;
 
@@ -408,8 +392,8 @@ void lem1802_reset_(struct dcpu16 *vm, void *data) {
 }
 
 static
-void lem1802_cycle_(struct dcpu16 *vm, void *data) {
-    struct lem1802_ *display = (struct lem1802_ *)data;
+void lem1802_cycle_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct lem1802_ *display = (struct lem1802_ *)hw->data;
 
     (void)vm;
     /*
@@ -464,8 +448,8 @@ void lem1802_cycle_(struct dcpu16 *vm, void *data) {
 }
 
 static
-void lem1802_hwi_(struct dcpu16 *vm, void *data) {
-    struct lem1802_ *display = (struct lem1802_ *)data;
+void lem1802_hwi_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct lem1802_ *display = (struct lem1802_ *)hw->data;
     DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A];
     DCPU16_WORD reg_b = vm->reg[DCPU16_REG_B];
 
@@ -562,54 +546,63 @@ char *lem1802_renderers_iter(void **iterp, char **name, char **args) {
     return (*r)->name;
 }
 
-/* instantitate a new display */
-struct dcpu16_hw *lem1802_new(struct dcpu16 *vm) {
-    struct dcpu16_hw *hw;
-
-    hw = calloc(1, sizeof *hw);
-    if (hw == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
-        return NULL;
-    }
-
-    memcpy(hw, &hw_, sizeof *hw);
+int lem1802_data_init_(struct dcpu16_hw *hw, void *data) {
+    (void)data;
 
     hw->data = calloc(1, sizeof(struct lem1802_));
     if (hw->data == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
-        free(hw);
-        return NULL;
+        hw->vm->warn_cb_("%s():%s", "calloc", strerror(errno));
+        return -1;
     }
 
-    ((struct lem1802_ *)(hw->data))->pixbuf = calloc(1, PIX_X * PIX_Y * sizeof *((struct lem1802_ *)(hw->data))->pixbuf);
+    ((struct lem1802_ *)(hw->data))->pixbuf = calloc(PIX_X * PIX_Y, sizeof *((struct lem1802_ *)(hw->data))->pixbuf);
     if (((struct lem1802_ *)(hw->data))->pixbuf == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
+        hw->vm->warn_cb_("%s():%s", "calloc", strerror(errno));
         free(hw->data);
-        free(hw);
-        return NULL;
+        hw->data = NULL;
+        return -1;
     }
 
     ((struct lem1802_ *)(hw->data))->refresh_rate = 1666;
     ((struct lem1802_ *)(hw->data))->blink_rate = 75000;
 
-    hw->vm = vm;
-
-    return hw;
+    return 0;
 }
 
-void lem1802_del(struct dcpu16_hw **hw) {
+void lem1802_data_free_(struct dcpu16_hw *hw) {
     if (hw) {
-        if (*hw) {
-            if ((*hw)->data) {
-                if (((struct lem1802_ *)(*hw)->data)->pixbuf) {
-                    free(((struct lem1802_ *)(*hw)->data)->pixbuf);
-                    ((struct lem1802_ *)(*hw)->data)->pixbuf = NULL;
-                }
-                free((*hw)->data);
-                (*hw)->data = NULL;
+        if (hw->data) {
+            /* FIXME: free renderer data */
+            hw->vm->warn_cb_("FIXME");
+
+            if (((struct lem1802_ *)(hw->data))->pixbuf) {
+                free(((struct lem1802_ *)(hw->data))->pixbuf);
+                ((struct lem1802_ *)(hw->data))->pixbuf = NULL;
             }
-            free(*hw);
-            *hw = NULL;
+
+            free(hw->data);
+            hw->data = NULL;
         }
     }
 }
+
+
+static struct dcpu16_hw hw_ = {
+    .name_  = "LEM1802 - Low Energy Monitor",
+    .id_l   = 0xf615,
+    .id_h   = 0x7349,
+    .ver    = 0x1802,
+    .mfg_l  = 0x8b36,
+    .mfg_h  = 0x1c6c,
+    .hwi    = lem1802_hwi_,
+    .cycle  = lem1802_cycle_,
+    .reset  = lem1802_reset_,
+    .data   = (struct lem1802_ *)NULL
+};
+
+struct dcpu16_hw_module dcpu16_hw_module_lem1802 = {
+    .template = &hw_,
+    .data_init = lem1802_data_init_,
+    .data_free = lem1802_data_free_,
+};
+
index cc45d682bcafdc5d1e1b316ac377a8ea20e0aa6d..df333e9f8da87b298f8682f74beb23b71c1e9fe9 100644 (file)
@@ -7,10 +7,11 @@
 
 #include "dcpu16.h"
 
-struct dcpu16_hw *lem1802_new(struct dcpu16 *);
-void lem1802_del(struct dcpu16_hw **);
+extern struct dcpu16_hw_module dcpu16_hw_module_lem1802;
+
 int lem1802_renderer_set(struct dcpu16_hw *, const char *, void *);
 char *lem1802_renderers_iter(void **, char **, char **);
+
 #ifdef HAVE_LIBVNCSERVER
 rfbScreenInfoPtr lem1802_rfb_new(int argc, char *argv[]);
 void lem1802_vnc_associate(struct dcpu16_hw *, rfbScreenInfoPtr);
index 402a1d7949a2e150b768365cdc742a604d50e15a..f07489578b1157e80842a8ac0d7027761395ed99 100644 (file)
@@ -5,39 +5,14 @@
 #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_ = {
-    .vm     = NULL,
-    .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
-};
-
-static dcpu16_hw_data_init_t spc2000_data_init_;
-static dcpu16_hw_data_free_t spc2000_data_free_;
-struct dcpu16_hw_module dcpu16_hw_module_spc2000 = {
-    .template = &hw_,
-    .data_init = spc2000_data_init_,
-    .data_free = spc2000_data_free_,
-};
-
 struct spc2000_ {
     DCPU16_WORD skip_unit;
     long long skip;
 };
 
 static
-int spc2000_data_init_(struct dcpu16_hw *hw, void *extra) {
-    (void)extra;
+int spc2000_data_init_(struct dcpu16_hw *hw, void *data) {
+    (void)data;
 
     hw->data = calloc(1, sizeof(struct spc2000_));
     if (hw->data == NULL) {
@@ -58,8 +33,8 @@ void spc2000_data_free_(struct dcpu16_hw *hw) {
 }
 
 static
-void spc2000_reset_(struct dcpu16 *vm, void *data) {
-    struct spc2000_ *spc2000 = (struct spc2000_ *)data;
+void spc2000_reset_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct spc2000_ *spc2000 = (struct spc2000_ *)hw->data;
 
     (void)vm;
 
@@ -67,16 +42,16 @@ void spc2000_reset_(struct dcpu16 *vm, void *data) {
 }
 
 static
-void spc2000_cycle_(struct dcpu16 *vm, void *data) {
-    struct spc2000_ *spc2000 = (struct spc2000_ *)data;
+void spc2000_cycle_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct spc2000_ *spc2000 = (struct spc2000_ *)hw->data;
 
     (void)vm;
     (void)spc2000;
 }
 
 static
-void spc2000_hwi_(struct dcpu16 *vm, void *data) {
-    struct spc2000_ *spc2000 = (struct spc2000_ *)data;
+void spc2000_hwi_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
+    struct spc2000_ *spc2000 = (struct spc2000_ *)hw->data;
     DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A],
                 reg_b = vm->reg[DCPU16_REG_B];
     long long x;
@@ -110,38 +85,22 @@ void spc2000_hwi_(struct dcpu16 *vm, void *data) {
     }
 }
 
-struct dcpu16_hw *spc2000_new(struct dcpu16 *vm) {
-    struct dcpu16_hw *hw;
-
-    hw = calloc(1, sizeof *hw);
-    if (hw == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
-        return NULL;
-    }
-
-    memcpy(hw, &hw_, sizeof *hw);
-
-    hw->data = calloc(1, sizeof(struct spc2000_));
-    if (hw->data == NULL) {
-        vm->warn_cb_("%s():%s", "calloc", strerror(errno));
-        free(hw);
-        return NULL;
-    }
-
-    hw->vm = vm;
-
-    return hw;
-}
+static struct dcpu16_hw hw_ = {
+    .vm     = NULL,
+    .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
+};
 
-void spc2000_del(struct dcpu16_hw **hw) {
-    if (hw) {
-        if (*hw) {
-            if ((*hw)->data) {
-                free((*hw)->data);
-                (*hw)->data = NULL;
-            }
-            free(*hw);
-            *hw = NULL;
-        }
-    }
-}
+struct dcpu16_hw_module dcpu16_hw_module_spc2000 = {
+    .template = &hw_,
+    .data_init = spc2000_data_init_,
+    .data_free = spc2000_data_free_,
+};
index 5accf2f740ed5c76baaf0235896ff845c6860612..b8a35327b0721bc75961fa86a3746ac227b7a3e5 100644 (file)
@@ -533,7 +533,7 @@ COMMAND_IMPL(display) {
     if (arg_count == 3)
         renderer_arg = arg_vector[2];
 
-    hw = lem1802_new(vm);
+    hw = dcpu16_hw_new(vm, &dcpu16_hw_module_lem1802, NULL);
     if (hw == NULL) {
         fprintf(stderr, "failed to initialize new display\n");
         return 0;
@@ -542,16 +542,12 @@ COMMAND_IMPL(display) {
     /* handle per-renderer setup of data.. */
     /* FIXME: these are awkward */
     if (strcmp(renderer, "pnm") == 0) {
-        if (renderer_arg == NULL)
-            renderer_arg = display_filename_default_;
-        renderer_data = (void *)renderer_arg;
+        renderer_data = (void *)(renderer_arg ? renderer_arg : display_filename_default_);
     }
 
 #ifdef HAVE_LIBPNG
     if (strcmp(renderer, "png") == 0) {
-        if (renderer_arg == NULL)
-            renderer_arg = display_filename_default_;
-        renderer_data = (void *)renderer_arg;
+        renderer_data = (void *)(renderer_arg ? renderer_arg : display_filename_default_);
     }
 #endif /* HAVE_LIBPNG */
 
@@ -564,7 +560,7 @@ COMMAND_IMPL(display) {
         s = rfbScreen_next_available_display_(&rfbScreens_, argc, argv);
         if (s == NULL) {
             fprintf(stderr, "failed to initialize vnc\n");
-            lem1802_del(&hw);
+            dcpu16_hw_del(&hw);
             return 0;
         }
 
@@ -577,13 +573,13 @@ COMMAND_IMPL(display) {
 
     if (lem1802_renderer_set(hw, renderer, renderer_data)) {
         fprintf(stderr, "failed to set back-end renderer for display\n");
-        lem1802_del(&hw);
+        dcpu16_hw_del(&hw);
         return 0;
     }
 
-    if (dcpu16_hw_add(vm, hw)) {
+    if (dcpu16_hw_attach(vm, hw)) {
         fprintf(stderr, "failed to attach new display\n");
-        lem1802_del(&hw);
+        dcpu16_hw_del(&hw);
         return 0;
     }
 
@@ -611,7 +607,7 @@ COMMAND_IMPL(keyboard) {
 
     (void)arg_count, (void)arg_vector;
 
-    hw = keyboard_new(vm);
+    hw = dcpu16_hw_new(vm, &dcpu16_hw_module_keyboard, NULL);
     if (hw == NULL) {
         fprintf(stderr, "failed to initialize new keyboard\n");
         return 0;
@@ -625,15 +621,15 @@ COMMAND_IMPL(keyboard) {
     s = rfbScreen_next_available_keyboard_(&rfbScreens_, argc, argv);
     if (s == NULL) {
         fprintf(stderr, "failed to initialize vnc\n");
-        keyboard_del(&hw);
+        dcpu16_hw_del(&hw);
         return 0;
     }
     keyboard_vnc_associate(hw, s->screen);
     s->attached_keyboard = hw;
 
-    if (dcpu16_hw_add(vm, hw)) {
+    if (dcpu16_hw_attach(vm, hw)) {
         fprintf(stderr, "failed to attach new keyboard\n");
-        keyboard_del(&hw);
+        dcpu16_hw_del(&hw);
         return 0;
     }
 #endif /* HAVE_LIBVNCSERVER */