changed some names/structs/typedefs around, mostly aesthetical
* TODO
* change api to print into buffers rather than stdio
* refactor opcode functiontables into switch statements
* TODO
* change api to print into buffers rather than stdio
* refactor opcode functiontables into switch statements
+ * let callbacks determine whether to override events, or just observe
+ * sort init callbacks by base addr, to call in-order
*/
static const char * const src_id_ = "$Id$";
*/
static const char * const src_id_ = "$Id$";
* Register callback fn to be triggered whenever event matching any events
* in bitwise mask occur.
*/
* Register callback fn to be triggered whenever event matching any events
* in bitwise mask occur.
*/
-int dcpu16_acct_add(struct dcpu16 *vm, dcpu16_acct_event mask, void (*fn)(struct dcpu16 *, dcpu16_acct_event, DCPU16_WORD, void *), void *data) {
+int dcpu16_acct_add(struct dcpu16 *vm, dcpu16_acct_event mask, dcpu16_ev_cb_t *fn, void *data) {
struct dcpu16_acct_cb cb;
cb.mask = mask;
struct dcpu16_acct_cb cb;
cb.mask = mask;
/* a self-contained dcpu16 core */
struct dcpu16 {
/* a self-contained dcpu16 core */
struct dcpu16 {
+ struct dcpu16_acct_cb *cb_table_; /* list of callbacks to invoke for certain events */
+ size_t cb_table_entries_; /* callback list maintenance */
+ size_t cb_table_allocated_; /* callback list maintenance */
+ unsigned int skip_ : 1; /* skip execution of next instruction */
+ DCPU16_WORD reg_work_[2]; /* work registers for holding literal values while decoding instructions */
+
unsigned long long cycle; /* number of cycles this core has executed */
DCPU16_WORD reg[8]; /* system registers, a b c x y z i j */
DCPU16_WORD pc; /* program counter */
DCPU16_WORD sp; /* stack pointer */
DCPU16_WORD o; /* overflow */
unsigned long long cycle; /* number of cycles this core has executed */
DCPU16_WORD reg[8]; /* system registers, a b c x y z i j */
DCPU16_WORD pc; /* program counter */
DCPU16_WORD sp; /* stack pointer */
DCPU16_WORD o; /* overflow */
- unsigned int skip_ : 1; /* skip execution of next instruction */
DCPU16_WORD ram[DCPU16_RAM]; /* memory */
DCPU16_WORD ram[DCPU16_RAM]; /* memory */
- DCPU16_WORD reg_work_[2]; /* (private) work registers for holding literal values while decoding instructions */
- struct dcpu16_acct_cb *cb_table_; /* list of callbacks to invoke for certain events */
- size_t cb_table_entries_; /* callback list maintenance */
- size_t cb_table_allocated_; /* callback list maintenance */
-/* these are used for accounting/watchpointing/&c */
+/* these are used for accounting/watchpointing/modules/&c */
typedef unsigned int dcpu16_acct_event;
typedef unsigned int dcpu16_acct_event;
+typedef void (dcpu16_ev_cb_t)(struct dcpu16 *, dcpu16_acct_event, DCPU16_WORD, void *);
#define DCPU16_ACCT_EV_READ (1<<1)
#define DCPU16_ACCT_EV_WRITE (1<<2)
#define DCPU16_ACCT_EV_NOP (1<<3)
#define DCPU16_ACCT_EV_RESET (1<<4)
struct dcpu16_acct_cb {
#define DCPU16_ACCT_EV_READ (1<<1)
#define DCPU16_ACCT_EV_WRITE (1<<2)
#define DCPU16_ACCT_EV_NOP (1<<3)
#define DCPU16_ACCT_EV_RESET (1<<4)
struct dcpu16_acct_cb {
- void (*fn)(struct dcpu16 *, dcpu16_acct_event e, DCPU16_WORD addr, void *);
void *data;
dcpu16_acct_event mask;
};
void *data;
dcpu16_acct_event mask;
};
DCPU16_WORD dcpu16_disassemble_print(struct dcpu16 *, DCPU16_WORD);
/* register a callback for an accounting event */
DCPU16_WORD dcpu16_disassemble_print(struct dcpu16 *, DCPU16_WORD);
/* register a callback for an accounting event */
-int dcpu16_acct_add(struct dcpu16 *, dcpu16_acct_event mask, void (*fn)(struct dcpu16 *, dcpu16_acct_event, DCPU16_WORD, void *), void *data);
+int dcpu16_acct_add(struct dcpu16 *, dcpu16_acct_event mask, dcpu16_ev_cb_t *fn, void *data);
/* execute the next instruction */
void dcpu16_step(struct dcpu16 *);
/* execute the next instruction */
void dcpu16_step(struct dcpu16 *);
+struct dcpu16_display_ {
+ char *outfile;
+ struct pixel_ *pixbuf;
+};
+
-DPIX pcolor_(unsigned int c) {
- DPIX p = { 0, 0, 0 };
+struct pixel_ pcolor_(unsigned int c) {
+ struct pixel_ p = { 0, 0, 0 };
switch (c) {
case 0x1: p.r=0x00, p.g=0x00, p.b=0xaa; break; /* dark blue */
switch (c) {
case 0x1: p.r=0x00, p.g=0x00, p.b=0xaa; break; /* dark blue */
/* should this just flood-fill entire display? */
static inline
/* should this just flood-fill entire display? */
static inline
-void display_draw_border(DPIX *pixbuf, DPIX color) {
+void display_draw_border(struct pixel_ *pixbuf, struct pixel_ color) {
/* render a character cell to the display */
static inline
/* render a character cell to the display */
static inline
-void display_draw_cell(DPIX *pixbuf, DCPU16_WORD *cell_map, DCPU16_WORD index, int cell_x, int cell_y, DPIX fg, DPIX bg) {
- DPIX *cellstart = pixbuf; /* start of display */
+void display_draw_cell(struct pixel_ *pixbuf, DCPU16_WORD *cell_map, DCPU16_WORD index, int cell_x, int cell_y, struct pixel_ fg, struct pixel_ bg) {
+ struct pixel_ *cellstart = pixbuf; /* start of display */
unsigned int pix_x, pix_y;
unsigned char *cell_bitmap = (unsigned char *)(cell_map + (index * sizeof index));
unsigned int pix_x, pix_y;
unsigned char *cell_bitmap = (unsigned char *)(cell_map + (index * sizeof index));
-void display_pnm_write(DPIX *pixbuf, const char *filename) {
+void display_pnm_write(struct pixel_ *pixbuf, const char *filename) {
/* currently this populates the chargen map 'from rom'.. */
/* and clears the display buffers */
void display_reset_fn(struct dcpu16 *vm, dcpu16_acct_event e, DCPU16_WORD addr, void *data) {
/* currently this populates the chargen map 'from rom'.. */
/* and clears the display buffers */
void display_reset_fn(struct dcpu16 *vm, dcpu16_acct_event e, DCPU16_WORD addr, void *data) {
- DPIX *pixbuf = (DPIX *)data;
+ struct dcpu16_display_ *d = (struct dcpu16_display_ *)data;
- fprintf(stderr, "DEBUG: event:%u\n", e);
-
- fprintf(stderr, "DEBUG: loading chargen map from 0x%04x to 0x%04x (%zuo)\n",
- DISPLAY_CELL_MAP,
- DISPLAY_CELL_MAP + (unsigned short)(sizeof chargen_4x8_glyphs / sizeof addr),
- sizeof chargen_4x8_glyphs);
memcpy(vm->ram + DISPLAY_CELL_MAP, chargen_4x8_glyphs, sizeof chargen_4x8_glyphs);
memcpy(vm->ram + DISPLAY_CELL_MAP, chargen_4x8_glyphs, sizeof chargen_4x8_glyphs);
- fprintf(stderr, "DEBUG: clearing display buffer from 0x%04x to 0x%04x (%zuo)\n",
- DISPLAY_BASE,
- DISPLAY_END,
- (DISPLAY_END - DISPLAY_BASE) * sizeof *(vm->ram));
memset(vm->ram + DISPLAY_BASE, 0, (DISPLAY_END - DISPLAY_BASE) * sizeof *(vm->ram));
memset(vm->ram + DISPLAY_BASE, 0, (DISPLAY_END - DISPLAY_BASE) * sizeof *(vm->ram));
- fprintf(stderr, "DEBUG: clearing pixel buffer (%zuo)\n",
- PIX_X * PIX_Y * sizeof *pixbuf);
- memset(pixbuf, 0, PIX_X * PIX_Y * sizeof *pixbuf);
+ memset(d->pixbuf, 0, PIX_X * PIX_Y * sizeof *(d->pixbuf));
}
/* the callback to register with the cpu for watching memory updates */
/* user data is an allocated display buffer */
void display_fn(struct dcpu16 *vm, dcpu16_acct_event e, DCPU16_WORD addr, void *data) {
}
/* the callback to register with the cpu for watching memory updates */
/* user data is an allocated display buffer */
void display_fn(struct dcpu16 *vm, dcpu16_acct_event e, DCPU16_WORD addr, void *data) {
- const char * const outfile = "dcpu16-display.pnm";
- DPIX *pixbuf = (DPIX *)data;
+ DCPU16_DISPLAY *d = (DCPU16_DISPLAY *)data;
unsigned char index, blink, bg, fg;
unsigned int cell_x, cell_y;
unsigned char index, blink, bg, fg;
unsigned int cell_x, cell_y;
blink = (vm->ram[addr] >> 7) & 0x01;
bg = (vm->ram[addr] >> 8) & 0x0f;
fg = (vm->ram[addr] >> 12) & 0x0f;
blink = (vm->ram[addr] >> 7) & 0x01;
bg = (vm->ram[addr] >> 8) & 0x0f;
fg = (vm->ram[addr] >> 12) & 0x0f;
- display_draw_cell(pixbuf, vm->ram + DISPLAY_CELL_MAP, index, cell_x, cell_y, pcolor_(fg), pcolor_(bg));
+ display_draw_cell(d->pixbuf, vm->ram + DISPLAY_CELL_MAP, index, cell_x, cell_y, pcolor_(fg), pcolor_(bg));
- display_pnm_write(pixbuf, outfile);
+ display_pnm_write(d->pixbuf, d->outfile);
return;
}
if (addr == DISPLAY_MISC) {
/* new border color */
char border = vm->ram[addr] & 0x0f;
return;
}
if (addr == DISPLAY_MISC) {
/* new border color */
char border = vm->ram[addr] & 0x0f;
- fprintf(stderr, "display event: new border\n");
- display_draw_border(pixbuf, pcolor_(border));
+ display_draw_border(d->pixbuf, pcolor_(border));
- display_pnm_write(pixbuf, outfile);
+ display_pnm_write(d->pixbuf, d->outfile);
bg = (vm->ram[addr] >> 8) & 0x0f;
fg = (vm->ram[addr] >> 12) & 0x0f;
bg = (vm->ram[addr] >> 8) & 0x0f;
fg = (vm->ram[addr] >> 12) & 0x0f;
- fprintf(stderr, "display event: cell %ux%u:%u '%c'\n", cell_x, cell_y, index, index);
-
- display_draw_cell(pixbuf, vm->ram + DISPLAY_CELL_MAP, index, cell_x, cell_y, pcolor_(fg), pcolor_(bg));
- display_pnm_write(pixbuf, outfile);
+ display_draw_cell(d->pixbuf, vm->ram + DISPLAY_CELL_MAP, index, cell_x, cell_y, pcolor_(fg), pcolor_(bg));
+ display_pnm_write(d->pixbuf, d->outfile);
}
/* init the pixel buffer */
}
/* init the pixel buffer */
-DPIX *display_init_pixbuf(void) {
- DPIX *pixbuf;
+DCPU16_DISPLAY *display_new(const char *filename) {
+ DCPU16_DISPLAY *d = calloc(1, sizeof *d);
+ if (d == NULL)
+ return NULL;
+
+ d->pixbuf = calloc(PIX_X * PIX_Y, sizeof *(d->pixbuf));
+ if (d->pixbuf == NULL) {
+ free(d);
+ return NULL;
+ }
- pixbuf = calloc(PIX_X * PIX_Y, sizeof *pixbuf);
+ d->outfile = strdup(filename);
+ if (d->outfile == NULL) {
+ free(d->pixbuf);
+ free(d);
+ return NULL;
+ }
-typedef struct pixel_ DPIX;
+typedef struct dcpu16_display_ DCPU16_DISPLAY;
void display_reset_fn(struct dcpu16 *, dcpu16_acct_event, DCPU16_WORD, void *);
void display_fn(struct dcpu16 *, dcpu16_acct_event, DCPU16_WORD, void *);
void display_reset_fn(struct dcpu16 *, dcpu16_acct_event, DCPU16_WORD, void *);
void display_fn(struct dcpu16 *, dcpu16_acct_event, DCPU16_WORD, void *);
-DPIX *display_init_pixbuf(void);
+DCPU16_DISPLAY *display_new(const char *filename);
#endif /* DISPLAY_H_MJYI1IAV */
#endif /* DISPLAY_H_MJYI1IAV */
COMMAND_IMPL(display) {
(void)arg_count, (void)arg_vector;
COMMAND_IMPL(display) {
(void)arg_count, (void)arg_vector;
- static DPIX *pixbuf = NULL;
+ static DCPU16_DISPLAY *display = NULL;
printf("display already enabled..\n");
return 0;
}
printf("display already enabled..\n");
return 0;
}
- pixbuf = display_init_pixbuf();
- if (pixbuf == NULL) {
+ display = display_new("dcpu16-display.pnm");
+ if (display == NULL) {
fprintf(stderr, "failed to initialize display buffer\n");
return 0;
}
fprintf(stderr, "failed to initialize display buffer\n");
return 0;
}
- if (dcpu16_acct_add(vm, DCPU16_ACCT_EV_WRITE, display_fn, pixbuf)) {
+ if (dcpu16_acct_add(vm, DCPU16_ACCT_EV_WRITE, display_fn, display)) {
fprintf(stderr, "failed to register display update callback\n");
return 0;
}
fprintf(stderr, "failed to register display update callback\n");
return 0;
}
- if (dcpu16_acct_add(vm, DCPU16_ACCT_EV_RESET, display_reset_fn, pixbuf)) {
+ if (dcpu16_acct_add(vm, DCPU16_ACCT_EV_RESET, display_reset_fn, display)) {
fprintf(stderr, "failed to register display reset callback\n");
return 0;
}
/* init display as if reset occurred */
fprintf(stderr, "failed to register display reset callback\n");
return 0;
}
/* init display as if reset occurred */
- display_reset_fn(vm, DCPU16_ACCT_EV_RESET, 0, pixbuf);
+ display_reset_fn(vm, DCPU16_ACCT_EV_RESET, 0, display);