From fdd6efd9ad3e0e213a50ed962ec628c17779794a Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Sun, 7 May 2023 23:57:23 +0100 Subject: Report non recoverable errors on the player --- example.asm | 1 + font.h | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tr8vm.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++------- vm.c | 63 +++++++++++++++------------- vm.h | 1 + 5 files changed, 279 insertions(+), 44 deletions(-) create mode 100644 font.h diff --git a/example.asm b/example.asm index 992823f..7584074 100644 --- a/example.asm +++ b/example.asm @@ -76,6 +76,7 @@ update_done: call draw_sprite ; wait 1 frame + sif halt pop b diff --git a/font.h b/font.h new file mode 100644 index 0000000..9385f09 --- /dev/null +++ b/font.h @@ -0,0 +1,135 @@ +#ifndef _FONT_H +#define _FONT_H + +static uint8_t font[128][8] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e }, + { 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e }, + { 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00 }, + { 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00 }, + { 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c }, + { 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c }, + { 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00 }, + { 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff }, + { 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00 }, + { 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff }, + { 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78 }, + { 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18 }, + { 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0 }, + { 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0 }, + { 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99 }, + { 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00 }, + { 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00 }, + { 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18 }, + { 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00 }, + { 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00 }, + { 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78 }, + { 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00 }, + { 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff }, + { 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00 }, + { 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00 }, + { 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00 }, + { 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00 }, + { 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00 }, + { 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00 }, + { 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00 }, + { 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00 }, + { 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00 }, + { 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00 }, + { 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00 }, + { 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00 }, + { 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00 }, + { 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00 }, + { 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00 }, + { 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60 }, + { 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00 }, + { 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00 }, + { 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00 }, + { 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00 }, + { 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00 }, + { 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00 }, + { 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00 }, + { 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00 }, + { 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00 }, + { 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00 }, + { 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00 }, + { 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00 }, + { 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00 }, + { 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60 }, + { 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00 }, + { 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00 }, + { 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00 }, + { 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00 }, + { 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00 }, + { 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00 }, + { 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00 }, + { 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00 }, + { 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00 }, + { 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00 }, + { 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00 }, + { 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00 }, + { 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00 }, + { 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 }, + { 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00 }, + { 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00 }, + { 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00 }, + { 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00 }, + { 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00 }, + { 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00 }, + { 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00 }, + { 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00 }, + { 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00 }, + { 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00 }, + { 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 }, + { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00 }, + { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00 }, + { 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00 }, + { 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00 }, + { 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00 }, + { 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00 }, + { 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00 }, + { 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00 }, + { 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00 }, + { 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff }, + { 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00 }, + { 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00 }, + { 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00 }, + { 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00 }, + { 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00 }, + { 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00 }, + { 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8 }, + { 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00 }, + { 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 }, + { 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78 }, + { 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00 }, + { 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 }, + { 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00 }, + { 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00 }, + { 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00 }, + { 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0 }, + { 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e }, + { 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00 }, + { 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00 }, + { 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00 }, + { 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00 }, + { 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00 }, + { 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00 }, + { 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00 }, + { 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8 }, + { 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00 }, + { 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00 }, + { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00 }, + { 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00 }, + { 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00 }, +}; + +#endif /* _FONT_H */ diff --git a/tr8vm.c b/tr8vm.c index 59d08b7..7d254e0 100644 --- a/tr8vm.c +++ b/tr8vm.c @@ -30,7 +30,9 @@ #include "vm.h" -#define ARGB(r, g, b) ((uint32_t)(((r)<<16)|((g)<<8)|(b))) +#include "font.h" + +#define ARGB(r, g, b) ((uint32_t)(0xff000000|((r)<<16)|((g)<<8)|(b))) #define APP_NAME "TR8 VM Player" #define APP_VERSION "0.1-alpha" @@ -91,6 +93,47 @@ static uint32_t palette[] = ARGB(0xff, 0xff, 0xff), }; +uint32_t *ui_data = NULL; + +static void ui_put_glyph(uint32_t x, uint32_t y, uint8_t c) +{ + uint32_t *p = ui_data + x + (y * WINDOW_W); + + for (uint8_t j = 0; j < 8; j++) + for (uint8_t i = 0; i < 8; i++) + if (font[c][j] & (128 >> i)) + p[i + j * WINDOW_W] = palette[12]; +} + +static void ui_put_text(uint32_t x, uint32_t y, char *text) +{ + uint32_t ox = x; + + while (*text) + { + uint8_t c = *text++; + + if (c == '\n') + { + y += 12; + if (y > WINDOW_H) + break; + + x = ox; + continue; + } + + ui_put_glyph(x, y, c); + + x += 8; + if (x > WINDOW_W) + { + x = 0; + y += 12; + } + } +} + uint8_t ram[UINT16_MAX + 1] = { 0 }; uint32_t *fb_data = NULL; @@ -234,6 +277,14 @@ int main(int argc, char *argv[]) } SDL_SetTextureBlendMode(fb, SDL_BLENDMODE_NONE); + SDL_Texture *ui = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, WINDOW_W, WINDOW_H); + if (!ui) + { + fprintf(stderr, "Failed to create the UI: %s\n", SDL_GetError()); + return 1; + } + SDL_SetTextureBlendMode(ui, SDL_BLENDMODE_BLEND); + int fullscreen = 0; SDL_Rect dst; resize_full_screen(screen, renderer, fullscreen, &dst); @@ -244,7 +295,7 @@ int main(int argc, char *argv[]) Tr8 vm; tr8_init(&vm, write_m, read_m, port); int pitch = 0; - uint8_t rc; + uint8_t rc = 1; /* update full fb once to sync with RAM */ pitch = 0; @@ -253,6 +304,13 @@ int main(int argc, char *argv[]) update_fb(); SDL_UnlockTexture(fb); + /* prepare UI layer */ + pitch = 0; + ui_data = NULL; + SDL_LockTexture(ui, NULL, (void **)&ui_data, &pitch); + memset(ui_data, 0x20202080, sizeof(uint32_t) * WINDOW_W * WINDOW_H); + SDL_UnlockTexture(ui); + SDL_Event ev; while (1) { @@ -278,14 +336,29 @@ int main(int argc, char *argv[]) } } - pitch = 0; - fb_data = NULL; - SDL_LockTexture(fb, NULL, (void **)&fb_data, &pitch); - rc = tr8_eval(&vm); - SDL_UnlockTexture(fb); + if (rc) + { + pitch = 0; + fb_data = NULL; + SDL_LockTexture(fb, NULL, (void **)&fb_data, &pitch); + rc = tr8_eval(&vm); + SDL_UnlockTexture(fb); - if (!rc) - break; + if (!rc) + { + /* non recoverable error */ + pitch = 0; + ui_data = NULL; + SDL_LockTexture(ui, NULL, (void **)&ui_data, &pitch); + ui_put_text(10, 10, "[VM HALT]"); + + char buffer[256]; + tr8_dump(&vm, buffer); + ui_put_text(10, 22, buffer); + + SDL_UnlockTexture(ui); + } + } /* render to the canvas */ SDL_SetRenderTarget(renderer, canvas); @@ -298,16 +371,34 @@ int main(int argc, char *argv[]) SDL_RenderClear(renderer); SDL_RenderCopy(renderer, canvas, NULL, &dst); + if (!rc) + SDL_RenderCopy(renderer, ui, NULL, &dst); + SDL_RenderPresent(renderer); - pitch = 0; - fb_data = NULL; - SDL_LockTexture(fb, NULL, (void **)&fb_data, &pitch); - rc = tr8_frame_int(&vm); - SDL_UnlockTexture(fb); + if (rc) + { + pitch = 0; + fb_data = NULL; + SDL_LockTexture(fb, NULL, (void **)&ui_data, &pitch); + rc = tr8_frame_int(&vm); + SDL_UnlockTexture(fb); - if (!rc) - break; + if (!rc) + { + /* non recoverable error */ + pitch = 0; + ui_data = NULL; + SDL_LockTexture(ui, NULL, (void **)&fb_data, &pitch); + ui_put_text(10, 10, "[VM HALT]"); + + char buffer[256]; + tr8_dump(&vm, buffer); + ui_put_text(10, 22, buffer); + + SDL_UnlockTexture(ui); + } + } } if (canvas) diff --git a/vm.c b/vm.c index 5f4b1ce..ff6bcb8 100644 --- a/vm.c +++ b/vm.c @@ -69,42 +69,49 @@ static uint8_t flags(uint8_t *f, uint16_t v, uint8_t mask) return v; } -static void dump(Tr8 *vm) +void tr8_dump(Tr8 *vm, char *buffer) { uint8_t i; + size_t s; - fprintf(stderr, " PC 0x%04x: ", vm->pc); - for (i = 0; i < 16 && i + vm->pc < UINT16_MAX + 1; i++) - fprintf(stderr, "0x%02x ", vm->read_m(vm->pc + i)); - fprintf(stderr, "\n"); + s = sprintf(buffer, " PC 0x%04x: ", vm->pc); + for (i = 0; i < 8 && i + vm->pc < UINT16_MAX + 1; i++) + s += sprintf(buffer + s, "0x%02x ", vm->read_m(vm->pc + i)); + s += sprintf(buffer + s, "\n"); - fprintf(stderr, " SP 0x%04x: ", vm->sp); + s += sprintf(buffer + s, " SP 0x%04x: ", vm->sp); if (vm->sp == vm->ssp) - fprintf(stderr, "-"); + s += sprintf(buffer + s, "-"); else { - for (i = 0; i < 16 && i + vm->sp < UINT16_MAX + 1; i++) - fprintf(stderr, "0x%02x ", vm->read_m(vm->sp + i)); + for (i = 0; i < 8 && i + vm->sp < UINT16_MAX + 1; i++) + s += sprintf(buffer + s, "0x%02x ", vm->read_m(vm->sp + i)); } - fprintf(stderr, "\n"); - - fprintf(stderr, " F: %c%c%c%c%c%c\n" - " A: 0x%02x B: 0x%02x\n" - " X: 0x%02x Y: 0x%02x\n\n" - " %d instr run\n", - (vm->f & ZF) ? 'Z' : 'z', - (vm->f & CF) ? 'C' : 'c', - (vm->f & OF) ? 'O' : 'o', - (vm->f & SF) ? 'S' : 's', - (vm->f & IF) ? 'I' : 'i', - (vm->f & BF) ? 'B' : 'b', - vm->regs[0], - vm->regs[1], - vm->regs[2], - vm->regs[3], - vm->icnt); - - fprintf(stderr, "****\n"); + s += sprintf(buffer + s, "\n"); + + s += sprintf(buffer + s, " F: %c%c%c%c%c%c\n" + " A: 0x%02x B: 0x%02x\n" + " X: 0x%02x Y: 0x%02x\n\n" + " %d instr run\n", + (vm->f & ZF) ? 'Z' : 'z', + (vm->f & CF) ? 'C' : 'c', + (vm->f & OF) ? 'O' : 'o', + (vm->f & SF) ? 'S' : 's', + (vm->f & IF) ? 'I' : 'i', + (vm->f & BF) ? 'B' : 'b', + vm->regs[0], + vm->regs[1], + vm->regs[2], + vm->regs[3], + vm->icnt); +} + +static void dump(Tr8 *vm) +{ + char buffer[256]; + + tr8_dump(vm, buffer); + fputs(buffer, stderr); } void tr8_init(Tr8 *vm, void (*write_m)(uint16_t, uint8_t), uint8_t (*read_m)(uint16_t), uint8_t (*port)(uint8_t, uint8_t)) diff --git a/vm.h b/vm.h index 118ea25..f66f8c9 100644 --- a/vm.h +++ b/vm.h @@ -45,5 +45,6 @@ typedef struct void tr8_init(Tr8 *vm, void (*write_m)(uint16_t, uint8_t), uint8_t (*read_m)(uint16_t), uint8_t (*port)(uint8_t, uint8_t)); uint8_t tr8_eval(Tr8 *vm); uint8_t tr8_frame_int(Tr8 *vm); +void tr8_dump(Tr8 *vm, char *buffer); #endif /* _TR8_H */ -- cgit v1.2.3