Added rewind and underclocking support to the SDL port. Joystick controls to be done.
This commit is contained in:
parent
2791775c5d
commit
1915365b1a
98
SDL/gui.c
98
SDL/gui.c
@ -62,10 +62,15 @@ configuration_t configuration =
|
||||
SDL_SCANCODE_RETURN,
|
||||
SDL_SCANCODE_SPACE
|
||||
},
|
||||
.keys_2 = {
|
||||
SDL_SCANCODE_TAB,
|
||||
SDL_SCANCODE_LSHIFT,
|
||||
},
|
||||
.color_correction_mode = GB_COLOR_CORRECTION_EMULATE_HARDWARE,
|
||||
.highpass_mode = GB_HIGHPASS_ACCURATE,
|
||||
.scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR,
|
||||
.blend_frames = true,
|
||||
.rewind_length = 60 * 2,
|
||||
.model = MODEL_CGB
|
||||
};
|
||||
|
||||
@ -282,8 +287,55 @@ const char *current_model_string(unsigned index)
|
||||
[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[] = {
|
||||
{"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},
|
||||
{NULL,}
|
||||
};
|
||||
@ -486,16 +538,15 @@ static void enter_audio_menu(unsigned index)
|
||||
current_menu = audio_menu;
|
||||
current_selection = 0;
|
||||
}
|
||||
static const char *key_name(unsigned index)
|
||||
{
|
||||
return SDL_GetScancodeName(configuration.keys[index]);
|
||||
}
|
||||
|
||||
static void modify_key(unsigned index)
|
||||
{
|
||||
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[] = {
|
||||
{"Right:", 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,},
|
||||
{"Select:", 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},
|
||||
{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)
|
||||
{
|
||||
current_menu = controls_menu;
|
||||
current_selection = 0;
|
||||
}
|
||||
|
||||
static void enter_controls_menu_2(unsigned index)
|
||||
{
|
||||
current_menu = controls_menu_2;
|
||||
current_selection = 0;
|
||||
}
|
||||
|
||||
static unsigned joypad_index = 0;
|
||||
SDL_Joystick *joystick = NULL;
|
||||
SDL_GameController *controller = NULL;
|
||||
@ -906,7 +982,17 @@ void run_gui(bool is_running)
|
||||
should_render = true;
|
||||
}
|
||||
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;
|
||||
should_render = true;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <stdbool.h>
|
||||
#include "shader.h"
|
||||
|
||||
extern GB_gameboy_t gb;
|
||||
|
||||
extern SDL_Window *window;
|
||||
extern SDL_Renderer *renderer;
|
||||
@ -51,6 +52,10 @@ typedef struct {
|
||||
MODEL_AGB,
|
||||
MODEL_MAX,
|
||||
} model;
|
||||
|
||||
/* v0.11 */
|
||||
uint32_t rewind_length;
|
||||
SDL_Scancode keys_2[2]; /* Rewind and underclock */
|
||||
} configuration_t;
|
||||
|
||||
extern configuration_t configuration;
|
||||
|
44
SDL/main.c
44
SDL/main.c
@ -1,6 +1,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <Core/gb.h>
|
||||
#include "utils.h"
|
||||
@ -25,6 +26,8 @@ GB_gameboy_t gb;
|
||||
static bool paused = false;
|
||||
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 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 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);
|
||||
}
|
||||
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 {
|
||||
@ -152,9 +156,6 @@ static void handle_events(GB_gameboy_t *gb)
|
||||
SDL_PauseAudioDevice(device_id, 1);
|
||||
}
|
||||
run_gui(true);
|
||||
if (!audio_playing) {
|
||||
SDL_PauseAudioDevice(device_id, 0);
|
||||
}
|
||||
GB_set_color_correction_mode(gb, configuration.color_correction_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
|
||||
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 {
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
render_texture(active_pixel_buffer, previous_pixel_buffer);
|
||||
uint32_t *temp = active_pixel_buffer;
|
||||
@ -296,6 +316,7 @@ static void vblank(GB_gameboy_t *gb)
|
||||
else {
|
||||
render_texture(active_pixel_buffer, NULL);
|
||||
}
|
||||
do_rewind = rewind_down;
|
||||
handle_events(gb);
|
||||
}
|
||||
|
||||
@ -381,6 +402,7 @@ restart:
|
||||
GB_set_sample_rate(&gb, have_aspec.freq);
|
||||
GB_set_color_correction_mode(&gb, configuration.color_correction_mode);
|
||||
GB_set_highpass_filter_mode(&gb, configuration.highpass_mode);
|
||||
GB_set_rewind_length(&gb, configuration.rewind_length);
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
@ -410,11 +432,21 @@ restart:
|
||||
|
||||
/* Run emulation */
|
||||
while (true) {
|
||||
if (paused) {
|
||||
if (paused || rewind_paused) {
|
||||
SDL_WaitEvent(NULL);
|
||||
handle_events(&gb);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user