From d2a8386f725892f7850dcf7a507634c0a3725ad2 Mon Sep 17 00:00:00 2001 From: Stefan Arentz Date: Sun, 15 Oct 2017 16:40:30 -0400 Subject: [PATCH] Fixes #178 - Allow the emulator to be paused --- src/CMakeLists.txt | 2 +- src/Makefile | 2 +- src/boo.c | 3 ++- src/one.c | 12 ++++++++---- src/tty.c | 38 +++++++++++++++++++++++++++-------- src/tty.h | 6 +++++- src/two.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-- src/two.h | 7 +++++++ 8 files changed, 101 insertions(+), 18 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2b9525d..1135310 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,7 +15,7 @@ set(SDL_SOURCES sdl.c) set(BOO_SOURCES boo.c tty.c chr.c) set(ONE_SOURCES one.c tty.c chr.c pia.c) -set(TWO_SOURCES two.c scr.c dsk.c chr.c alc.c) +set(TWO_SOURCES two.c scr.c dsk.c chr.c alc.c tty.c) add_executable(cpu_test ${CPU_SOURCES} cpu_test.c) diff --git a/src/Makefile b/src/Makefile index 39f2818..2d3b794 100644 --- a/src/Makefile +++ b/src/Makefile @@ -61,7 +61,7 @@ CPU_TEST_OBJECTS=$(CPU_TEST_SOURCES:.c=.o) CPU_TEST_LIBS=$(LUA_LIBS) SCR_TEST_EXECUTABLE=scr_test -SCR_TEST_SOURCES=$(CPU_SOURCES) two.c scr.c dsk.c chr.c alc.c scr_test.c sdl.c +SCR_TEST_SOURCES=$(CPU_SOURCES) two.c scr.c dsk.c chr.c alc.c scr_test.c sdl.c tty.c SCR_TEST_OBJECTS=$(SCR_TEST_SOURCES:.c=.o) SCR_TEST_LIBS=-lSDL2 $(LUA_LIBS) diff --git a/src/boo.c b/src/boo.c index 9739cca..7fe0ee9 100644 --- a/src/boo.c +++ b/src/boo.c @@ -85,7 +85,8 @@ int ewm_boo_main(int argc, char **argv) { // We only need a tty to display the menu - struct ewm_tty_t *tty = ewm_tty_create(renderer); + SDL_Color green = {255,255,0,255}; + struct ewm_tty_t *tty = ewm_tty_create(renderer, green); // Main loop diff --git a/src/one.c b/src/one.c index 73a7638..60d7230 100644 --- a/src/one.c +++ b/src/one.c @@ -45,24 +45,28 @@ static int ewm_one_init(struct ewm_one_t *one, int model, SDL_Renderer *renderer memset(one, 0, sizeof(struct ewm_one_t)); one->model = model; switch (model) { - case EWM_ONE_MODEL_APPLE1: + case EWM_ONE_MODEL_APPLE1: { one->cpu = cpu_create(EWM_CPU_MODEL_6502); cpu_add_ram(one->cpu, 0x0000, 8 * 1024 - 1); cpu_add_rom_file(one->cpu, 0xff00, "rom/apple1.rom"); - one->tty = ewm_tty_create(renderer); + SDL_Color green = {0,255,0,255}; + one->tty = ewm_tty_create(renderer, green); one->pia = ewm_pia_create(one->cpu); one->pia->callback = ewm_one_pia_callback; one->pia->callback_obj = one; break; - case EWM_ONE_MODEL_REPLICA1: + } + case EWM_ONE_MODEL_REPLICA1: { one->cpu = cpu_create(EWM_CPU_MODEL_65C02); cpu_add_ram(one->cpu, 0x0000, 32 * 1024 - 1); cpu_add_rom_file(one->cpu, 0xe000, "rom/krusader.rom"); - one->tty = ewm_tty_create(renderer); + SDL_Color green = {0,255,0,255}; + one->tty = ewm_tty_create(renderer, green); one->pia = ewm_pia_create(one->cpu); one->pia->callback = ewm_one_pia_callback; one->pia->callback_obj = one; break; + } } return 0; } diff --git a/src/tty.c b/src/tty.c index 22298aa..40ccf1f 100644 --- a/src/tty.c +++ b/src/tty.c @@ -24,7 +24,7 @@ #include "sdl.h" #include "tty.h" -struct ewm_tty_t *ewm_tty_create(SDL_Renderer *renderer) { +struct ewm_tty_t *ewm_tty_create(SDL_Renderer *renderer, SDL_Color color) { struct ewm_tty_t *tty = malloc(sizeof(struct ewm_tty_t)); memset(tty, 0, sizeof(struct ewm_tty_t)); tty->renderer = renderer; @@ -35,6 +35,8 @@ struct ewm_tty_t *ewm_tty_create(SDL_Renderer *renderer) { EWM_ONE_TTY_ROWS * ewm_chr_height(tty->chr), 32, 4 * EWM_ONE_TTY_COLUMNS * ewm_chr_width(tty->chr), ewm_sdl_pixel_format(renderer)); + tty->screen_cursor_enabled = 1; + tty->color = SDL_MapRGBA(tty->surface->format, color.r, color.g, color.b, color.a); ewm_tty_reset(tty); return tty; } @@ -67,7 +69,15 @@ static inline void ewm_tty_render_character(struct ewm_tty_t *tty, int row, int uint32_t *dst = tty->pixels + ((40 * 7 * 8) * row) + (7 * column); for (int y = 0; y < 8; y++) { for (int x = 0; x < 7; x++) { - *dst++ = *src++; + *dst++ = *src++ ? tty->color : 0; // TODO Can be optimized by moving color into chr + } + dst += (40 * 7) - 7; + } + } else { + uint32_t *dst = tty->pixels + ((40 * 7 * 8) * row) + (7 * column); + for (int y = 0; y < 8; y++) { + for (int x = 0; x < 7; x++) { + *dst++ = 0; } dst += (40 * 7) - 7; } @@ -114,6 +124,14 @@ void ewm_tty_reset(struct ewm_tty_t *tty) { tty->screen_dirty = true; } +void ewm_tty_set_line(struct ewm_tty_t *tty, int v, char *line) { + if (v < 24) { + char buf[41]; + snprintf(buf, 40, "%-40s", line); + memcpy(tty->screen_buffer + (v * 40), buf, 40); + } +} + void ewm_tty_refresh(struct ewm_tty_t *tty, uint32_t phase, uint32_t fps) { for (int row = 0; row < 24; row++) { for (int column = 0; column < 40; column++) { @@ -121,13 +139,17 @@ void ewm_tty_refresh(struct ewm_tty_t *tty, uint32_t phase, uint32_t fps) { } } - if ((phase % (fps / 4)) == 0) { - tty->screen_cursor_blink = !tty->screen_cursor_blink; + if (phase != 0 && fps != 0) { + if ((phase % (fps / 4)) == 0) { + tty->screen_cursor_blink = !tty->screen_cursor_blink; + } } - if (tty->screen_cursor_blink) { - ewm_tty_render_character(tty, tty->screen_cursor_row, tty->screen_cursor_column, EWM_ONE_TTY_CURSOR_ON); - } else { - ewm_tty_render_character(tty, tty->screen_cursor_row, tty->screen_cursor_column, EWM_ONE_TTY_CURSOR_OFF); + if (tty->screen_cursor_enabled) { + if (tty->screen_cursor_blink) { + ewm_tty_render_character(tty, tty->screen_cursor_row, tty->screen_cursor_column, EWM_ONE_TTY_CURSOR_ON); + } else { + ewm_tty_render_character(tty, tty->screen_cursor_row, tty->screen_cursor_column, EWM_ONE_TTY_CURSOR_OFF); + } } } diff --git a/src/tty.h b/src/tty.h index 41e70ff..51352d9 100644 --- a/src/tty.h +++ b/src/tty.h @@ -40,18 +40,22 @@ struct ewm_tty_t { struct ewm_chr_t *chr; bool screen_dirty; uint8_t screen_buffer[EWM_ONE_TTY_ROWS * EWM_ONE_TTY_COLUMNS]; + + int screen_cursor_enabled; int screen_cursor_row; int screen_cursor_column; int screen_cursor_blink; uint32_t *pixels; SDL_Surface *surface; + uint32_t color; }; -struct ewm_tty_t *ewm_tty_create(SDL_Renderer *renderer); +struct ewm_tty_t *ewm_tty_create(SDL_Renderer *renderer, SDL_Color color); void ewm_tty_destroy(struct ewm_tty_t *tty); void ewm_tty_write(struct ewm_tty_t *tty, uint8_t v); void ewm_tty_reset(struct ewm_tty_t *tty); +void ewm_tty_set_line(struct ewm_tty_t *tty, int v, char *line); void ewm_tty_refresh(struct ewm_tty_t *tty, uint32_t phase, uint32_t fps); #endif // EWM_TTY_H diff --git a/src/two.c b/src/two.c index b236619..017bef4 100644 --- a/src/two.c +++ b/src/two.c @@ -37,6 +37,7 @@ #if defined(EWM_LUA) #include "lua.h" #endif +#include "tty.h" #include "two.h" @@ -303,6 +304,14 @@ static int ewm_two_init(struct ewm_two_t *two, int type, SDL_Renderer *renderer, return -1; } + SDL_Color red = {255,0,0,255}; + two->tty = ewm_tty_create(renderer, red); + if (two->tty == NULL) { + fprintf(stderr, "[TWO] Could not create status tty\n"); + return -1; + } + two->tty->screen_cursor_enabled = 0; + break; } @@ -522,6 +531,13 @@ static bool ewm_two_poll_event(struct ewm_two_t *two, SDL_Window *window) { // T SDL_SetWindowSize(window, 40*7*3, 24*8*3 + (two->status_bar_visible ? (9*3) : 0)); SDL_RenderSetLogicalSize(two->scr->renderer, 40*7*3, 24*8*3 + (two->status_bar_visible ? (9*3) : 0)); break; + case SDLK_p: + if (two->state == EWM_TWO_STATE_PAUSED) { + two->state = EWM_TWO_STATE_RUNNING; + } else { + two->state = EWM_TWO_STATE_PAUSED; + } + break; } } else if (event.key.keysym.mod == KMOD_NONE) { switch (event.key.keysym.sym) { @@ -706,6 +722,28 @@ static void usage() { #endif } +static void ewm_two_render_status(struct ewm_two_t *two, char *msg) { + SDL_SetRenderDrawColor(two->scr->renderer, 0, 0, 0, 224); + SDL_RenderFillRect(two->scr->renderer, NULL); + + ewm_tty_reset(two->tty); + + ewm_tty_set_line(two->tty, 8, " ******************** "); + ewm_tty_set_line(two->tty, 9, " * * "); + ewm_tty_set_line(two->tty, 10, " * -+- PAUSED -+- * "); + ewm_tty_set_line(two->tty, 11, " * * "); + ewm_tty_set_line(two->tty, 12, " ******************** "); + + ewm_tty_refresh(two->tty, 0, 0); + + SDL_Texture *texture = SDL_CreateTextureFromSurface(two->tty->renderer, two->tty->surface); + if (texture != NULL) { + SDL_SetRenderDrawBlendMode(two->scr->renderer, SDL_BLENDMODE_BLEND); + SDL_RenderCopy(two->tty->renderer, texture, NULL, NULL); + SDL_DestroyTexture(texture); + } +} + int ewm_two_main(int argc, char **argv) { // Parse options @@ -910,8 +948,11 @@ int ewm_two_main(int argc, char **argv) { } if ((SDL_GetTicks() - ticks) >= (1000 / fps)) { - if (!ewm_two_step_cpu(two, EWM_TWO_SPEED / fps)) { - break; + + if (two->state == EWM_TWO_STATE_RUNNING) { + if (!ewm_two_step_cpu(two, EWM_TWO_SPEED / fps)) { + break; + } } // Update the screen when it is flagged dirty or if we enter @@ -936,6 +977,10 @@ int ewm_two_main(int argc, char **argv) { SDL_DestroyTexture(texture); } + if (two->state == EWM_TWO_STATE_PAUSED) { + ewm_two_render_status(two, "PAUSED"); + } + SDL_RenderPresent(two->scr->renderer); } diff --git a/src/two.h b/src/two.h index 311588b..bb899a9 100644 --- a/src/two.h +++ b/src/two.h @@ -53,10 +53,14 @@ #define EWM_TWO_FPS_DEFAULT (30) #define EWM_TWO_SPEED (1023000) +#define EWM_TWO_STATE_RUNNING (0) +#define EWM_TWO_STATE_PAUSED (1) + struct mem_t; struct ewm_dsk_t; struct scr; struct ewm_lua_t; +struct ewm_tty_t; struct ewm_two_t { int type; @@ -96,6 +100,9 @@ struct ewm_two_t { int lua_key_down_fn; int lua_key_up_fn; + + int state; + struct ewm_tty_t *tty; }; struct ewm_two_t *ewm_two_create(int type, SDL_Renderer *renderer, SDL_Joystick *joystick);