Added rewind and underclocking support to the SDL port. Joystick controls to be done.

This commit is contained in:
Lior Halphon 2018-06-23 00:10:28 +03:00
parent 2791775c5d
commit 1915365b1a
3 changed files with 135 additions and 12 deletions

View File

@ -62,10 +62,15 @@ configuration_t configuration =
SDL_SCANCODE_RETURN, SDL_SCANCODE_RETURN,
SDL_SCANCODE_SPACE SDL_SCANCODE_SPACE
}, },
.keys_2 = {
SDL_SCANCODE_TAB,
SDL_SCANCODE_LSHIFT,
},
.color_correction_mode = GB_COLOR_CORRECTION_EMULATE_HARDWARE, .color_correction_mode = GB_COLOR_CORRECTION_EMULATE_HARDWARE,
.highpass_mode = GB_HIGHPASS_ACCURATE, .highpass_mode = GB_HIGHPASS_ACCURATE,
.scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR, .scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR,
.blend_frames = true, .blend_frames = true,
.rewind_length = 60 * 2,
.model = MODEL_CGB .model = MODEL_CGB
}; };
@ -282,8 +287,55 @@ const char *current_model_string(unsigned index)
[configuration.model]; [configuration.model];
} }
static const uint32_t rewind_lengths[] = {0, 10, 30, 60, 60 * 2, 60 * 5, 60 * 10};
static const char *rewind_strings[] = {"Disabled",
"10 Seconds",
"30 Seconds",
"1 Minute",
"2 Minutes",
"5 Minutes",
"10 Minutes",
};
static void cycle_rewind(unsigned index)
{
for (unsigned i = 0; i < sizeof(rewind_lengths) / sizeof(rewind_lengths[0]) - 1; i++) {
if (configuration.rewind_length == rewind_lengths[i]) {
configuration.rewind_length = rewind_lengths[i + 1];
GB_set_rewind_length(&gb, configuration.rewind_length);
return;
}
}
configuration.rewind_length = rewind_lengths[0];
GB_set_rewind_length(&gb, configuration.rewind_length);
}
static void cycle_rewind_backwards(unsigned index)
{
for (unsigned i = 1; i < sizeof(rewind_lengths) / sizeof(rewind_lengths[0]); i++) {
if (configuration.rewind_length == rewind_lengths[i]) {
configuration.rewind_length = rewind_lengths[i - 1];
GB_set_rewind_length(&gb, configuration.rewind_length);
return;
}
}
configuration.rewind_length = rewind_lengths[sizeof(rewind_lengths) / sizeof(rewind_lengths[0]) - 1];
GB_set_rewind_length(&gb, configuration.rewind_length);
}
const char *current_rewind_string(unsigned index)
{
for (unsigned i = 0; i < sizeof(rewind_lengths) / sizeof(rewind_lengths[0]); i++) {
if (configuration.rewind_length == rewind_lengths[i]) {
return rewind_strings[i];
}
}
return "Custom";
}
static const struct menu_item emulation_menu[] = { static const struct menu_item emulation_menu[] = {
{"Emulated Model:", cycle_model, current_model_string, cycle_model_backwards}, {"Emulated Model:", cycle_model, current_model_string, cycle_model_backwards},
{"Rewind Length:", cycle_rewind, current_rewind_string, cycle_rewind_backwards},
{"Back", return_to_root_menu}, {"Back", return_to_root_menu},
{NULL,} {NULL,}
}; };
@ -486,16 +538,15 @@ static void enter_audio_menu(unsigned index)
current_menu = audio_menu; current_menu = audio_menu;
current_selection = 0; current_selection = 0;
} }
static const char *key_name(unsigned index)
{
return SDL_GetScancodeName(configuration.keys[index]);
}
static void modify_key(unsigned index) static void modify_key(unsigned index)
{ {
gui_state = WAITING_FOR_KEY; gui_state = WAITING_FOR_KEY;
} }
static void enter_controls_menu_2(unsigned index);
static const char *key_name(unsigned index);
static const struct menu_item controls_menu[] = { static const struct menu_item controls_menu[] = {
{"Right:", modify_key, key_name,}, {"Right:", modify_key, key_name,},
{"Left:", modify_key, key_name,}, {"Left:", modify_key, key_name,},
@ -505,17 +556,42 @@ static const struct menu_item controls_menu[] = {
{"B:", modify_key, key_name,}, {"B:", modify_key, key_name,},
{"Select:", modify_key, key_name,}, {"Select:", modify_key, key_name,},
{"Start:", modify_key, key_name,}, {"Start:", modify_key, key_name,},
{"Turbo:", modify_key, key_name,}, {"Next Page", enter_controls_menu_2},
{"Back", return_to_root_menu}, {"Back", return_to_root_menu},
{NULL,} {NULL,}
}; };
static const struct menu_item controls_menu_2[] = {
{"Turbo:", modify_key, key_name,},
{"Rewind:", modify_key, key_name,},
{"Slow-Motion:", modify_key, key_name,},
{"Back", return_to_root_menu},
{NULL,}
};
static const char *key_name(unsigned index)
{
if (current_menu == controls_menu_2) {
if (index == 0) {
return SDL_GetScancodeName(configuration.keys[8]);
}
return SDL_GetScancodeName(configuration.keys_2[index - 1]);
}
return SDL_GetScancodeName(configuration.keys[index]);
}
static void enter_controls_menu(unsigned index) static void enter_controls_menu(unsigned index)
{ {
current_menu = controls_menu; current_menu = controls_menu;
current_selection = 0; current_selection = 0;
} }
static void enter_controls_menu_2(unsigned index)
{
current_menu = controls_menu_2;
current_selection = 0;
}
static unsigned joypad_index = 0; static unsigned joypad_index = 0;
SDL_Joystick *joystick = NULL; SDL_Joystick *joystick = NULL;
SDL_GameController *controller = NULL; SDL_GameController *controller = NULL;
@ -906,7 +982,17 @@ void run_gui(bool is_running)
should_render = true; should_render = true;
} }
else if (gui_state == WAITING_FOR_KEY) { else if (gui_state == WAITING_FOR_KEY) {
configuration.keys[current_selection] = event.key.keysym.scancode; if (current_menu == controls_menu_2) {
if (current_selection == 0) {
configuration.keys[8] = event.key.keysym.scancode;
}
else {
configuration.keys_2[current_selection - 1] = event.key.keysym.scancode;
}
}
else {
configuration.keys[current_selection] = event.key.keysym.scancode;
}
gui_state = SHOWING_MENU; gui_state = SHOWING_MENU;
should_render = true; should_render = true;
} }

View File

@ -6,6 +6,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "shader.h" #include "shader.h"
extern GB_gameboy_t gb;
extern SDL_Window *window; extern SDL_Window *window;
extern SDL_Renderer *renderer; extern SDL_Renderer *renderer;
@ -51,6 +52,10 @@ typedef struct {
MODEL_AGB, MODEL_AGB,
MODEL_MAX, MODEL_MAX,
} model; } model;
/* v0.11 */
uint32_t rewind_length;
SDL_Scancode keys_2[2]; /* Rewind and underclock */
} configuration_t; } configuration_t;
extern configuration_t configuration; extern configuration_t configuration;

View File

@ -1,6 +1,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include <unistd.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <Core/gb.h> #include <Core/gb.h>
#include "utils.h" #include "utils.h"
@ -25,6 +26,8 @@ GB_gameboy_t gb;
static bool paused = false; static bool paused = false;
static uint32_t pixel_buffer_1[160*144], pixel_buffer_2[160*144]; static uint32_t pixel_buffer_1[160*144], pixel_buffer_2[160*144];
static uint32_t *active_pixel_buffer = pixel_buffer_1, *previous_pixel_buffer = pixel_buffer_2; static uint32_t *active_pixel_buffer = pixel_buffer_1, *previous_pixel_buffer = pixel_buffer_2;
static bool underclock_down = false, rewind_down = false, do_rewind = false, rewind_paused = false, turbo_down = false;
static double clock_mutliplier = 1.0;
static char *filename = NULL; static char *filename = NULL;
static bool should_free_filename = false; static bool should_free_filename = false;
@ -143,7 +146,8 @@ static void handle_events(GB_gameboy_t *gb)
GB_set_key_state(gb, GB_KEY_RIGHT, event.type == SDL_JOYBUTTONDOWN); GB_set_key_state(gb, GB_KEY_RIGHT, event.type == SDL_JOYBUTTONDOWN);
} }
else if (event.jbutton.button & 1) { else if (event.jbutton.button & 1) {
GB_set_turbo_mode(gb, event.type == SDL_JOYBUTTONDOWN, false); turbo_down = event.type == SDL_JOYBUTTONDOWN;
GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down);
} }
else { else {
@ -152,9 +156,6 @@ static void handle_events(GB_gameboy_t *gb)
SDL_PauseAudioDevice(device_id, 1); SDL_PauseAudioDevice(device_id, 1);
} }
run_gui(true); run_gui(true);
if (!audio_playing) {
SDL_PauseAudioDevice(device_id, 0);
}
GB_set_color_correction_mode(gb, configuration.color_correction_mode); GB_set_color_correction_mode(gb, configuration.color_correction_mode);
GB_set_highpass_filter_mode(gb, configuration.highpass_mode); GB_set_highpass_filter_mode(gb, configuration.highpass_mode);
} }
@ -268,7 +269,18 @@ static void handle_events(GB_gameboy_t *gb)
} }
case SDL_KEYUP: // Fallthrough case SDL_KEYUP: // Fallthrough
if (event.key.keysym.scancode == configuration.keys[8]) { if (event.key.keysym.scancode == configuration.keys[8]) {
GB_set_turbo_mode(gb, event.type == SDL_KEYDOWN, false); turbo_down = event.type == SDL_KEYDOWN;
GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down);
}
else if (event.key.keysym.scancode == configuration.keys_2[0]) {
rewind_down = event.type == SDL_KEYDOWN;
if (event.type == SDL_KEYUP) {
rewind_paused = false;
}
GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down);
}
else if (event.key.keysym.scancode == configuration.keys_2[1]) {
underclock_down = event.type == SDL_KEYDOWN;
} }
else { else {
for (unsigned i = 0; i < GB_KEY_MAX; i++) { for (unsigned i = 0; i < GB_KEY_MAX; i++) {
@ -286,6 +298,14 @@ static void handle_events(GB_gameboy_t *gb)
static void vblank(GB_gameboy_t *gb) static void vblank(GB_gameboy_t *gb)
{ {
if (underclock_down && clock_mutliplier > 0.5) {
clock_mutliplier -= 0.1;
GB_set_clock_multiplier(gb, clock_mutliplier);
}
else if (!underclock_down && clock_mutliplier < 1.0) {
clock_mutliplier += 0.1;
GB_set_clock_multiplier(gb, clock_mutliplier);
}
if (configuration.blend_frames) { if (configuration.blend_frames) {
render_texture(active_pixel_buffer, previous_pixel_buffer); render_texture(active_pixel_buffer, previous_pixel_buffer);
uint32_t *temp = active_pixel_buffer; uint32_t *temp = active_pixel_buffer;
@ -296,6 +316,7 @@ static void vblank(GB_gameboy_t *gb)
else { else {
render_texture(active_pixel_buffer, NULL); render_texture(active_pixel_buffer, NULL);
} }
do_rewind = rewind_down;
handle_events(gb); handle_events(gb);
} }
@ -381,6 +402,7 @@ restart:
GB_set_sample_rate(&gb, have_aspec.freq); GB_set_sample_rate(&gb, have_aspec.freq);
GB_set_color_correction_mode(&gb, configuration.color_correction_mode); GB_set_color_correction_mode(&gb, configuration.color_correction_mode);
GB_set_highpass_filter_mode(&gb, configuration.highpass_mode); GB_set_highpass_filter_mode(&gb, configuration.highpass_mode);
GB_set_rewind_length(&gb, configuration.rewind_length);
} }
bool error = false; bool error = false;
@ -410,11 +432,21 @@ restart:
/* Run emulation */ /* Run emulation */
while (true) { while (true) {
if (paused) { if (paused || rewind_paused) {
SDL_WaitEvent(NULL); SDL_WaitEvent(NULL);
handle_events(&gb); handle_events(&gb);
} }
else { else {
if (do_rewind) {
GB_rewind_pop(&gb);
if (turbo_down) {
GB_rewind_pop(&gb);
}
if (!GB_rewind_pop(&gb)) {
rewind_paused = true;
}
do_rewind = false;
}
GB_run(&gb); GB_run(&gb);
} }