Fixes #178 - Allow the emulator to be paused

This commit is contained in:
Stefan Arentz 2017-10-15 16:40:30 -04:00
parent 7a68e0909b
commit d2a8386f72
8 changed files with 101 additions and 18 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);