SDL port: Resizing, resizing modes, and pause support

This commit is contained in:
Lior Halphon 2017-05-24 20:33:39 +03:00
parent 00439f4d49
commit 52e99adc32

View File

@ -5,6 +5,7 @@
#include <assert.h> #include <assert.h>
#include <signal.h> #include <signal.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#ifndef _WIN32 #ifndef _WIN32
#define AUDIO_FREQUENCY 96000 #define AUDIO_FREQUENCY 96000
#else #else
@ -28,6 +29,8 @@ static SDL_Texture *texture = NULL;
static SDL_PixelFormat *pixel_format = NULL; static SDL_PixelFormat *pixel_format = NULL;
static SDL_AudioSpec want_aspec, have_aspec; static SDL_AudioSpec want_aspec, have_aspec;
static bool paused = false;
static uint32_t pixels[160*144]; static uint32_t pixels[160*144];
GB_gameboy_t gb; GB_gameboy_t gb;
@ -39,8 +42,54 @@ static enum {
GB_SDL_NEW_FILE_COMMAND, GB_SDL_NEW_FILE_COMMAND,
GB_SDL_TOGGLE_MODEL_COMMAND, GB_SDL_TOGGLE_MODEL_COMMAND,
} pending_command; } pending_command;
static enum {
GB_SDL_SCALING_ENTIRE_WINDOW,
GB_SDL_SCALING_KEEP_RATIO,
GB_SDL_SCALING_INTEGER_FACTOR,
GB_SDL_SCALING_MAX,
} scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR;
static unsigned command_parameter; static unsigned command_parameter;
static void update_viewport(void)
{
int win_width, win_height;
SDL_GetWindowSize(window, &win_width, &win_height);
double x_factor = win_width / 160.0;
double y_factor = win_height / 144.0;
if (scaling_mode == GB_SDL_SCALING_INTEGER_FACTOR) {
x_factor = floor(x_factor);
y_factor = floor(y_factor);
}
if (scaling_mode != GB_SDL_SCALING_ENTIRE_WINDOW) {
if (x_factor > y_factor) {
x_factor = y_factor;
}
else {
y_factor = x_factor;
}
}
unsigned new_width = x_factor * 160;
unsigned new_height = y_factor * 144;
SDL_Rect rect = (SDL_Rect){(win_width - new_width) / 2, (win_height - new_height) /2,
new_width, new_height};
SDL_RenderSetViewport(renderer, &rect);
}
static void cycle_scaling(void)
{
scaling_mode++;
scaling_mode %= GB_SDL_SCALING_MAX;
update_viewport();
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
static void handle_events(GB_gameboy_t *gb) static void handle_events(GB_gameboy_t *gb)
{ {
static bool ctrl = false; static bool ctrl = false;
@ -54,7 +103,7 @@ static void handle_events(GB_gameboy_t *gb)
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
switch( event.type ){ switch (event.type) {
case SDL_QUIT: case SDL_QUIT:
GB_save_battery(gb, battery_save_path_ptr); GB_save_battery(gb, battery_save_path_ptr);
exit(0); exit(0);
@ -69,6 +118,12 @@ static void handle_events(GB_gameboy_t *gb)
break; break;
} }
case SDL_WINDOWEVENT: {
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
update_viewport();
}
}
case SDL_KEYDOWN: case SDL_KEYDOWN:
switch (event.key.keysym.sym) { switch (event.key.keysym.sym) {
case SDLK_c: case SDLK_c:
@ -91,6 +146,12 @@ static void handle_events(GB_gameboy_t *gb)
} }
break; break;
case SDLK_p:
if (MODIFIER) {
paused = !paused;
}
break;
case SDLK_m: case SDLK_m:
if (MODIFIER) { if (MODIFIER) {
#ifdef __APPLE__ #ifdef __APPLE__
@ -103,6 +164,10 @@ static void handle_events(GB_gameboy_t *gb)
} }
break; break;
case SDLK_TAB:
cycle_scaling();
break;
default: default:
/* Save states */ /* Save states */
if (event.key.keysym.sym >= SDLK_0 && event.key.keysym.sym <= SDLK_9) { if (event.key.keysym.sym >= SDLK_0 && event.key.keysym.sym <= SDLK_9) {
@ -330,7 +395,13 @@ restart:
/* Run emulation */ /* Run emulation */
while (true) { while (true) {
if (paused) {
SDL_WaitEvent(NULL);
handle_events(&gb);
}
else {
GB_run(&gb); GB_run(&gb);
}
switch (pending_command) { switch (pending_command) {
case GB_SDL_LOAD_STATE_COMMAND: case GB_SDL_LOAD_STATE_COMMAND:
case GB_SDL_SAVE_STATE_COMMAND: { case GB_SDL_SAVE_STATE_COMMAND: {
@ -400,7 +471,8 @@ usage:
SDL_Init( SDL_INIT_EVERYTHING ); SDL_Init( SDL_INIT_EVERYTHING );
window = SDL_CreateWindow("SameBoy v" xstr(VERSION), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window = SDL_CreateWindow("SameBoy v" xstr(VERSION), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
160, 144, SDL_WINDOW_OPENGL); 160 * 2, 144 * 2, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
SDL_SetWindowMinimumSize(window, 160, 144);
renderer = SDL_CreateRenderer(window, -1, 0); renderer = SDL_CreateRenderer(window, -1, 0);
texture = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_STREAMING, 160, 144); texture = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_STREAMING, 160, 144);
@ -437,17 +509,33 @@ usage:
SDL_Event event; SDL_Event event;
while (SDL_WaitEvent(&event)) while (SDL_WaitEvent(&event))
{ {
if (event.type == SDL_QUIT) { switch (event.type) {
case SDL_QUIT: {
exit(0); exit(0);
} }
else if (event.type == SDL_DROPFILE) { case SDL_WINDOWEVENT: {
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
update_viewport();
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
break;
}
case SDL_DROPFILE: {
filename = event.drop.file; filename = event.drop.file;
should_free_filename = true; should_free_filename = true;
goto start;
}
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_TAB) {
cycle_scaling();
}
break; break;
} }
} }
} }
start:
run(); // Never returns run(); // Never returns
return 0; return 0;
} }