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
1 changed files with 99 additions and 11 deletions

View File

@ -5,6 +5,7 @@
#include <assert.h>
#include <signal.h>
#include <SDL2/SDL.h>
#ifndef _WIN32
#define AUDIO_FREQUENCY 96000
#else
@ -28,6 +29,8 @@ static SDL_Texture *texture = NULL;
static SDL_PixelFormat *pixel_format = NULL;
static SDL_AudioSpec want_aspec, have_aspec;
static bool paused = false;
static uint32_t pixels[160*144];
GB_gameboy_t gb;
@ -39,8 +42,54 @@ static enum {
GB_SDL_NEW_FILE_COMMAND,
GB_SDL_TOGGLE_MODEL_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 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 bool ctrl = false;
@ -54,7 +103,7 @@ static void handle_events(GB_gameboy_t *gb)
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch( event.type ){
switch (event.type) {
case SDL_QUIT:
GB_save_battery(gb, battery_save_path_ptr);
exit(0);
@ -69,6 +118,12 @@ static void handle_events(GB_gameboy_t *gb)
break;
}
case SDL_WINDOWEVENT: {
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
update_viewport();
}
}
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_c:
@ -90,6 +145,12 @@ static void handle_events(GB_gameboy_t *gb)
pending_command = GB_SDL_TOGGLE_MODEL_COMMAND;
}
break;
case SDLK_p:
if (MODIFIER) {
paused = !paused;
}
break;
case SDLK_m:
if (MODIFIER) {
@ -103,6 +164,10 @@ static void handle_events(GB_gameboy_t *gb)
}
break;
case SDLK_TAB:
cycle_scaling();
break;
default:
/* Save states */
if (event.key.keysym.sym >= SDLK_0 && event.key.keysym.sym <= SDLK_9) {
@ -330,7 +395,13 @@ restart:
/* Run emulation */
while (true) {
GB_run(&gb);
if (paused) {
SDL_WaitEvent(NULL);
handle_events(&gb);
}
else {
GB_run(&gb);
}
switch (pending_command) {
case GB_SDL_LOAD_STATE_COMMAND:
case GB_SDL_SAVE_STATE_COMMAND: {
@ -400,7 +471,8 @@ usage:
SDL_Init( SDL_INIT_EVERYTHING );
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);
texture = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_STREAMING, 160, 144);
@ -437,17 +509,33 @@ usage:
SDL_Event event;
while (SDL_WaitEvent(&event))
{
if (event.type == SDL_QUIT) {
exit(0);
}
else if (event.type == SDL_DROPFILE) {
filename = event.drop.file;
should_free_filename = true;
break;
switch (event.type) {
case SDL_QUIT: {
exit(0);
}
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;
should_free_filename = true;
goto start;
}
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_TAB) {
cycle_scaling();
}
break;
}
}
}
start:
run(); // Never returns
return 0;
}