Added configurable controls
This commit is contained in:
parent
8e61098fec
commit
f48194f480
@ -967,13 +967,13 @@ uint8_t font[] = {
|
|||||||
|
|
||||||
|
|
||||||
/* CTRL symbol */
|
/* CTRL symbol */
|
||||||
_, X, X, X, _, X,
|
_, X, X, _, _, X,
|
||||||
|
X, _, _, X, _, _,
|
||||||
X, _, _, _, _, _,
|
X, _, _, _, _, _,
|
||||||
X, _, _, _, _, _,
|
X, _, _, _, _, _,
|
||||||
X, _, _, _, _, _,
|
X, _, _, _, _, _,
|
||||||
X, _, _, _, _, _,
|
X, _, _, X, _, _,
|
||||||
X, _, _, _, _, _,
|
_, X, X, _, _, _,
|
||||||
_, X, X, X, _, _,
|
|
||||||
_, _, _, _, _, _,
|
_, _, _, _, _, _,
|
||||||
|
|
||||||
X, X, _, X, X, X,
|
X, X, _, X, X, X,
|
||||||
|
231
SDL/gui.c
231
SDL/gui.c
@ -11,10 +11,8 @@ SDL_Window *window = NULL;
|
|||||||
SDL_Renderer *renderer = NULL;
|
SDL_Renderer *renderer = NULL;
|
||||||
SDL_Texture *texture = NULL;
|
SDL_Texture *texture = NULL;
|
||||||
SDL_PixelFormat *pixel_format = NULL;
|
SDL_PixelFormat *pixel_format = NULL;
|
||||||
enum scaling_mode scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR;
|
|
||||||
enum pending_command pending_command;
|
enum pending_command pending_command;
|
||||||
unsigned command_parameter;
|
unsigned command_parameter;
|
||||||
GB_color_correction_mode_t color_correction_mode = GB_COLOR_CORRECTION_EMULATE_HARDWARE;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#define MODIFIER_NAME " " CMD_STRING
|
#define MODIFIER_NAME " " CMD_STRING
|
||||||
@ -22,36 +20,39 @@ GB_color_correction_mode_t color_correction_mode = GB_COLOR_CORRECTION_EMULATE_H
|
|||||||
#define MODIFIER_NAME CTRL_STRING
|
#define MODIFIER_NAME CTRL_STRING
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
configuration_t configuration =
|
||||||
|
{
|
||||||
|
{ SDL_SCANCODE_RIGHT,
|
||||||
|
SDL_SCANCODE_LEFT,
|
||||||
|
SDL_SCANCODE_UP,
|
||||||
|
SDL_SCANCODE_DOWN,
|
||||||
|
SDL_SCANCODE_X,
|
||||||
|
SDL_SCANCODE_Z,
|
||||||
|
SDL_SCANCODE_BACKSPACE,
|
||||||
|
SDL_SCANCODE_RETURN,
|
||||||
|
SDL_SCANCODE_SPACE
|
||||||
|
},
|
||||||
|
GB_COLOR_CORRECTION_EMULATE_HARDWARE,
|
||||||
|
GB_SDL_SCALING_INTEGER_FACTOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static const char *help[] ={
|
static const char *help[] ={
|
||||||
"Drop a GB or GBC ROM\n"
|
"Drop a GB or GBC ROM\n"
|
||||||
"file to play.\n"
|
"file to play.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
"Controls:\n"
|
|
||||||
" D-Pad: Arrow Keys\n"
|
|
||||||
" A: X\n"
|
|
||||||
" B: Z\n"
|
|
||||||
" Start: Enter\n"
|
|
||||||
" Select: Backspace\n"
|
|
||||||
"\n"
|
|
||||||
" Turbo: Space\n"
|
|
||||||
" Menu: Escape\n",
|
|
||||||
"Keyboard Shortcuts:\n"
|
"Keyboard Shortcuts:\n"
|
||||||
|
" Open Menu: Escape\n"
|
||||||
" Reset: " MODIFIER_NAME "+R\n"
|
" Reset: " MODIFIER_NAME "+R\n"
|
||||||
" Pause: " MODIFIER_NAME "+P\n"
|
" Pause: " MODIFIER_NAME "+P\n"
|
||||||
" Toggle DMG/CGB: " MODIFIER_NAME "+T\n"
|
" Toggle DMG/CGB: " MODIFIER_NAME "+T\n"
|
||||||
"\n"
|
|
||||||
" Save state: " MODIFIER_NAME "+(0-9)\n"
|
" Save state: " MODIFIER_NAME "+(0-9)\n"
|
||||||
" Load state: " MODIFIER_NAME "+" SHIFT_STRING "+(0-9)\n"
|
" Load state: " MODIFIER_NAME "+" SHIFT_STRING "+(0-9)\n"
|
||||||
"\n"
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
" Mute/Unmute: " MODIFIER_NAME "+" SHIFT_STRING "+M\n"
|
" Mute/Unmute: " MODIFIER_NAME "+" SHIFT_STRING "+M\n"
|
||||||
#else
|
#else
|
||||||
" Mute/Unmute: " MODIFIER_NAME "+M\n"
|
" Mute/Unmute: " MODIFIER_NAME "+M\n"
|
||||||
#endif
|
#endif
|
||||||
" Cycle scaling modes: Tab"
|
|
||||||
"\n"
|
|
||||||
" Break Debugger: " CTRL_STRING "+C"
|
" Break Debugger: " CTRL_STRING "+C"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,12 +63,12 @@ void update_viewport(void)
|
|||||||
double x_factor = win_width / 160.0;
|
double x_factor = win_width / 160.0;
|
||||||
double y_factor = win_height / 144.0;
|
double y_factor = win_height / 144.0;
|
||||||
|
|
||||||
if (scaling_mode == GB_SDL_SCALING_INTEGER_FACTOR) {
|
if (configuration.scaling_mode == GB_SDL_SCALING_INTEGER_FACTOR) {
|
||||||
x_factor = (int)(x_factor);
|
x_factor = (int)(x_factor);
|
||||||
y_factor = (int)(y_factor);
|
y_factor = (int)(y_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scaling_mode != GB_SDL_SCALING_ENTIRE_WINDOW) {
|
if (configuration.scaling_mode != GB_SDL_SCALING_ENTIRE_WINDOW) {
|
||||||
if (x_factor > y_factor) {
|
if (x_factor > y_factor) {
|
||||||
x_factor = y_factor;
|
x_factor = y_factor;
|
||||||
}
|
}
|
||||||
@ -160,9 +161,9 @@ static void draw_text_centered(uint32_t *buffer, unsigned y, const char *string,
|
|||||||
|
|
||||||
struct menu_item {
|
struct menu_item {
|
||||||
const char *string;
|
const char *string;
|
||||||
void (*handler)(void);
|
void (*handler)(unsigned);
|
||||||
const char *(*value_getter)(void);
|
const char *(*value_getter)(unsigned);
|
||||||
void (*backwards_handler)(void);
|
void (*backwards_handler)(unsigned);
|
||||||
};
|
};
|
||||||
static const struct menu_item *current_menu = NULL;
|
static const struct menu_item *current_menu = NULL;
|
||||||
static const struct menu_item *root_menu = NULL;
|
static const struct menu_item *root_menu = NULL;
|
||||||
@ -172,25 +173,28 @@ static enum {
|
|||||||
SHOWING_DROP_MESSAGE,
|
SHOWING_DROP_MESSAGE,
|
||||||
SHOWING_MENU,
|
SHOWING_MENU,
|
||||||
SHOWING_HELP,
|
SHOWING_HELP,
|
||||||
|
WAITING_FOR_KEY,
|
||||||
} gui_state;
|
} gui_state;
|
||||||
|
|
||||||
static void item_exit(void)
|
static void item_exit(unsigned index)
|
||||||
{
|
{
|
||||||
pending_command = GB_SDL_QUIT_COMMAND;
|
pending_command = GB_SDL_QUIT_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned current_help_page = 0;
|
static unsigned current_help_page = 0;
|
||||||
static void item_help(void)
|
static void item_help(unsigned index)
|
||||||
{
|
{
|
||||||
current_help_page = 0;
|
current_help_page = 0;
|
||||||
gui_state = SHOWING_HELP;
|
gui_state = SHOWING_HELP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enter_graphics_menu(void);
|
static void enter_graphics_menu(unsigned index);
|
||||||
|
static void enter_controls_menu(unsigned index);
|
||||||
|
|
||||||
static const struct menu_item paused_menu[] = {
|
static const struct menu_item paused_menu[] = {
|
||||||
{"Resume", NULL},
|
{"Resume", NULL},
|
||||||
{"Graphic Options", enter_graphics_menu},
|
{"Graphic Options", enter_graphics_menu},
|
||||||
|
{"Controls", enter_controls_menu},
|
||||||
{"Help", item_help},
|
{"Help", item_help},
|
||||||
{"Exit", item_exit},
|
{"Exit", item_exit},
|
||||||
{NULL,}
|
{NULL,}
|
||||||
@ -198,26 +202,29 @@ static const struct menu_item paused_menu[] = {
|
|||||||
|
|
||||||
static const struct menu_item nonpaused_menu[] = {
|
static const struct menu_item nonpaused_menu[] = {
|
||||||
{"Graphic Options", enter_graphics_menu},
|
{"Graphic Options", enter_graphics_menu},
|
||||||
|
{"Controls", enter_controls_menu},
|
||||||
{"Help", item_help},
|
{"Help", item_help},
|
||||||
{"Exit", item_exit},
|
{"Exit", item_exit},
|
||||||
{NULL,}
|
{NULL,}
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *current_scaling_mode(void)
|
const char *current_scaling_mode(unsigned index)
|
||||||
{
|
{
|
||||||
return (const char *[]){"Fill Entire Window", "Retain Aspect Ratio", "Retain Integer Factor"}[scaling_mode];
|
return (const char *[]){"Fill Entire Window", "Retain Aspect Ratio", "Retain Integer Factor"}
|
||||||
|
[configuration.scaling_mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *current_color_correction_mode(void)
|
const char *current_color_correction_mode(unsigned index)
|
||||||
{
|
{
|
||||||
return (const char *[]){"Disabled", "Correct Color Curves", "Emulate Hardware", "Preserve Brightness"}[color_correction_mode];
|
return (const char *[]){"Disabled", "Correct Color Curves", "Emulate Hardware", "Preserve Brightness"}
|
||||||
|
[configuration.color_correction_mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
void cycle_scaling(void)
|
void cycle_scaling(unsigned index)
|
||||||
{
|
{
|
||||||
scaling_mode++;
|
configuration.scaling_mode++;
|
||||||
if (scaling_mode == GB_SDL_SCALING_MAX) {
|
if (configuration.scaling_mode == GB_SDL_SCALING_MAX) {
|
||||||
scaling_mode = 0;
|
configuration.scaling_mode = 0;
|
||||||
}
|
}
|
||||||
update_viewport();
|
update_viewport();
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
@ -225,13 +232,13 @@ void cycle_scaling(void)
|
|||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cycle_scaling_backwards(void)
|
void cycle_scaling_backwards(unsigned index)
|
||||||
{
|
{
|
||||||
if (scaling_mode == 0) {
|
if (configuration.scaling_mode == 0) {
|
||||||
scaling_mode = GB_SDL_SCALING_MAX - 1;
|
configuration.scaling_mode = GB_SDL_SCALING_MAX - 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
scaling_mode--;
|
configuration.scaling_mode--;
|
||||||
}
|
}
|
||||||
update_viewport();
|
update_viewport();
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
@ -239,28 +246,28 @@ void cycle_scaling_backwards(void)
|
|||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cycle_color_correction(void)
|
static void cycle_color_correction(unsigned index)
|
||||||
{
|
{
|
||||||
if (color_correction_mode == GB_COLOR_CORRECTION_PRESERVE_BRIGHTNESS) {
|
if (configuration.color_correction_mode == GB_COLOR_CORRECTION_PRESERVE_BRIGHTNESS) {
|
||||||
color_correction_mode = GB_COLOR_CORRECTION_DISABLED;
|
configuration.color_correction_mode = GB_COLOR_CORRECTION_DISABLED;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
color_correction_mode++;
|
configuration.color_correction_mode++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cycle_color_correction_backwards(void)
|
static void cycle_color_correction_backwards(unsigned index)
|
||||||
{
|
{
|
||||||
if (color_correction_mode == GB_COLOR_CORRECTION_DISABLED) {
|
if (configuration.color_correction_mode == GB_COLOR_CORRECTION_DISABLED) {
|
||||||
color_correction_mode = GB_COLOR_CORRECTION_PRESERVE_BRIGHTNESS;
|
configuration.color_correction_mode = GB_COLOR_CORRECTION_PRESERVE_BRIGHTNESS;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
color_correction_mode--;
|
configuration.color_correction_mode--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void return_to_root_menu(void)
|
static void return_to_root_menu(unsigned index)
|
||||||
{
|
{
|
||||||
current_menu = root_menu;
|
current_menu = root_menu;
|
||||||
current_selection = 0;
|
current_selection = 0;
|
||||||
@ -273,12 +280,42 @@ static const struct menu_item graphics_menu[] = {
|
|||||||
{NULL,}
|
{NULL,}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void enter_graphics_menu(void)
|
static void enter_graphics_menu(unsigned index)
|
||||||
{
|
{
|
||||||
current_menu = graphics_menu;
|
current_menu = graphics_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)
|
||||||
|
{
|
||||||
|
gui_state = WAITING_FOR_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct menu_item controls_menu[] = {
|
||||||
|
{"Right:", modify_key, key_name,},
|
||||||
|
{"Left:", modify_key, key_name,},
|
||||||
|
{"Up:", modify_key, key_name,},
|
||||||
|
{"Down:", modify_key, key_name,},
|
||||||
|
{"A:", modify_key, key_name,},
|
||||||
|
{"B:", modify_key, key_name,},
|
||||||
|
{"Select:", modify_key, key_name,},
|
||||||
|
{"Start:", modify_key, key_name,},
|
||||||
|
{"Turbo:", modify_key, key_name,},
|
||||||
|
{"Back", return_to_root_menu},
|
||||||
|
{NULL,}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void enter_controls_menu(unsigned index)
|
||||||
|
{
|
||||||
|
current_menu = controls_menu;
|
||||||
|
current_selection = 0;
|
||||||
|
}
|
||||||
|
|
||||||
extern void set_filename(const char *new_filename, bool new_should_free);
|
extern void set_filename(const char *new_filename, bool new_should_free);
|
||||||
void run_gui(bool is_running)
|
void run_gui(bool is_running)
|
||||||
{
|
{
|
||||||
@ -297,45 +334,12 @@ void run_gui(bool is_running)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pixels[160 * 144];
|
uint32_t pixels[160 * 144];
|
||||||
SDL_Event event;
|
SDL_Event event = {0,};
|
||||||
gui_state = is_running? SHOWING_MENU : SHOWING_DROP_MESSAGE;
|
gui_state = is_running? SHOWING_MENU : SHOWING_DROP_MESSAGE;
|
||||||
bool should_render = true;
|
bool should_render = true;
|
||||||
current_menu = root_menu = is_running? paused_menu : nonpaused_menu;
|
current_menu = root_menu = is_running? paused_menu : nonpaused_menu;
|
||||||
current_selection = 0;
|
current_selection = 0;
|
||||||
while (SDL_WaitEvent(&event)) {
|
do {
|
||||||
if (should_render) {
|
|
||||||
should_render = false;
|
|
||||||
memcpy(pixels, converted_background->pixels, sizeof(pixels));
|
|
||||||
|
|
||||||
switch (gui_state) {
|
|
||||||
case SHOWING_DROP_MESSAGE:
|
|
||||||
draw_text_centered(pixels, 116, "Drop a GB or GBC", gui_palette_native[3], gui_palette_native[0], false);
|
|
||||||
draw_text_centered(pixels, 128, "file to play", gui_palette_native[3], gui_palette_native[0], false);
|
|
||||||
break;
|
|
||||||
case SHOWING_MENU:
|
|
||||||
draw_text_centered(pixels, 16, "SameBoy", gui_palette_native[3], gui_palette_native[0], false);
|
|
||||||
unsigned i = 0, y = 40;
|
|
||||||
for (const struct menu_item *item = current_menu; item->string; item++, i++) {
|
|
||||||
draw_text_centered(pixels, y, item->string, gui_palette_native[3], gui_palette_native[0],
|
|
||||||
i == current_selection && !item->value_getter ? DECORATION_SELECTION : DECORATION_NONE);
|
|
||||||
y += 12;
|
|
||||||
if (item->value_getter) {
|
|
||||||
draw_text_centered(pixels, y, item->value_getter(), gui_palette_native[3], gui_palette_native[0],
|
|
||||||
i == current_selection ? DECORATION_ARROWS : DECORATION_NONE);
|
|
||||||
y += 12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SHOWING_HELP:
|
|
||||||
draw_text(pixels, 2, 2, help[current_help_page], gui_palette_native[3], gui_palette_native[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_UpdateTexture(texture, NULL, pixels, 160 * sizeof (uint32_t));
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
|
||||||
SDL_RenderPresent(renderer);
|
|
||||||
}
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_QUIT: {
|
case SDL_QUIT: {
|
||||||
if (!is_running) {
|
if (!is_running) {
|
||||||
@ -362,10 +366,7 @@ void run_gui(bool is_running)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
if (event.key.keysym.scancode == SDL_SCANCODE_TAB) {
|
if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) {
|
||||||
cycle_scaling();
|
|
||||||
}
|
|
||||||
else if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) {
|
|
||||||
if (is_running) {
|
if (is_running) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -376,6 +377,8 @@ void run_gui(bool is_running)
|
|||||||
else if (gui_state == SHOWING_MENU) {
|
else if (gui_state == SHOWING_MENU) {
|
||||||
gui_state = SHOWING_DROP_MESSAGE;
|
gui_state = SHOWING_DROP_MESSAGE;
|
||||||
}
|
}
|
||||||
|
current_selection = 0;
|
||||||
|
current_menu = root_menu;
|
||||||
should_render = true;
|
should_render = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,7 +394,7 @@ void run_gui(bool is_running)
|
|||||||
}
|
}
|
||||||
else if (event.key.keysym.scancode == SDL_SCANCODE_RETURN) {
|
else if (event.key.keysym.scancode == SDL_SCANCODE_RETURN) {
|
||||||
if (current_menu[current_selection].handler) {
|
if (current_menu[current_selection].handler) {
|
||||||
current_menu[current_selection].handler();
|
current_menu[current_selection].handler(current_selection);
|
||||||
if (pending_command) {
|
if (pending_command) {
|
||||||
if (!is_running && pending_command == GB_SDL_QUIT_COMMAND) {
|
if (!is_running && pending_command == GB_SDL_QUIT_COMMAND) {
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -405,11 +408,11 @@ void run_gui(bool is_running)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (event.key.keysym.scancode == SDL_SCANCODE_RIGHT && current_menu[current_selection].backwards_handler) {
|
else if (event.key.keysym.scancode == SDL_SCANCODE_RIGHT && current_menu[current_selection].backwards_handler) {
|
||||||
current_menu[current_selection].handler();
|
current_menu[current_selection].handler(current_selection);
|
||||||
should_render = true;
|
should_render = true;
|
||||||
}
|
}
|
||||||
else if (event.key.keysym.scancode == SDL_SCANCODE_LEFT && current_menu[current_selection].backwards_handler) {
|
else if (event.key.keysym.scancode == SDL_SCANCODE_LEFT && current_menu[current_selection].backwards_handler) {
|
||||||
current_menu[current_selection].backwards_handler();
|
current_menu[current_selection].backwards_handler(current_selection);
|
||||||
should_render = true;
|
should_render = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -420,7 +423,59 @@ void run_gui(bool is_running)
|
|||||||
}
|
}
|
||||||
should_render = true;
|
should_render = true;
|
||||||
}
|
}
|
||||||
|
else if (gui_state == WAITING_FOR_KEY) {
|
||||||
|
configuration.keys[current_selection] = event.key.keysym.scancode;
|
||||||
|
gui_state = SHOWING_MENU;
|
||||||
|
should_render = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (should_render) {
|
||||||
|
should_render = false;
|
||||||
|
memcpy(pixels, converted_background->pixels, sizeof(pixels));
|
||||||
|
|
||||||
|
switch (gui_state) {
|
||||||
|
case SHOWING_DROP_MESSAGE:
|
||||||
|
draw_text_centered(pixels, 116, "Drop a GB or GBC", gui_palette_native[3], gui_palette_native[0], false);
|
||||||
|
draw_text_centered(pixels, 128, "file to play", gui_palette_native[3], gui_palette_native[0], false);
|
||||||
|
break;
|
||||||
|
case SHOWING_MENU:
|
||||||
|
draw_text_centered(pixels, 8, "SameBoy", gui_palette_native[3], gui_palette_native[0], false);
|
||||||
|
unsigned i = 0, y = 24;
|
||||||
|
for (const struct menu_item *item = current_menu; item->string; item++, i++) {
|
||||||
|
if (item->value_getter && !item->backwards_handler) {
|
||||||
|
char line[25];
|
||||||
|
snprintf(line, sizeof(line), "%s%*s", item->string, 24 - (int)strlen(item->string), item->value_getter(i));
|
||||||
|
draw_text_centered(pixels, y, line, gui_palette_native[3], gui_palette_native[0],
|
||||||
|
i == current_selection ? DECORATION_SELECTION : DECORATION_NONE);
|
||||||
|
y += 12;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
draw_text_centered(pixels, y, item->string, gui_palette_native[3], gui_palette_native[0],
|
||||||
|
i == current_selection && !item->value_getter ? DECORATION_SELECTION : DECORATION_NONE);
|
||||||
|
y += 12;
|
||||||
|
if (item->value_getter) {
|
||||||
|
draw_text_centered(pixels, y, item->value_getter(i), gui_palette_native[3], gui_palette_native[0],
|
||||||
|
i == current_selection ? DECORATION_ARROWS : DECORATION_NONE);
|
||||||
|
y += 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SHOWING_HELP:
|
||||||
|
draw_text(pixels, 2, 2, help[current_help_page], gui_palette_native[3], gui_palette_native[0]);
|
||||||
|
break;
|
||||||
|
case WAITING_FOR_KEY:
|
||||||
|
draw_text_centered(pixels, 68, "Press a Key", gui_palette_native[3], gui_palette_native[0], DECORATION_NONE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_UpdateTexture(texture, NULL, pixels, 160 * sizeof (uint32_t));
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
}
|
||||||
|
} while (SDL_WaitEvent(&event));
|
||||||
|
}
|
||||||
|
10
SDL/gui.h
10
SDL/gui.h
@ -16,7 +16,6 @@ enum scaling_mode {
|
|||||||
GB_SDL_SCALING_MAX,
|
GB_SDL_SCALING_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern enum scaling_mode scaling_mode;
|
|
||||||
|
|
||||||
enum pending_command {
|
enum pending_command {
|
||||||
GB_SDL_NO_COMMAND,
|
GB_SDL_NO_COMMAND,
|
||||||
@ -30,10 +29,15 @@ enum pending_command {
|
|||||||
|
|
||||||
extern enum pending_command pending_command;
|
extern enum pending_command pending_command;
|
||||||
extern unsigned command_parameter;
|
extern unsigned command_parameter;
|
||||||
extern GB_color_correction_mode_t color_correction_mode;
|
typedef struct {
|
||||||
|
SDL_Scancode keys[9];
|
||||||
|
GB_color_correction_mode_t color_correction_mode;
|
||||||
|
enum scaling_mode scaling_mode;
|
||||||
|
} configuration_t;
|
||||||
|
|
||||||
|
extern configuration_t configuration;
|
||||||
|
|
||||||
void update_viewport(void);
|
void update_viewport(void);
|
||||||
void cycle_scaling(void);
|
|
||||||
|
|
||||||
void run_gui(bool is_running);
|
void run_gui(bool is_running);
|
||||||
#endif
|
#endif
|
||||||
|
43
SDL/main.c
43
SDL/main.c
@ -102,7 +102,7 @@ static void handle_events(GB_gameboy_t *gb)
|
|||||||
switch (event.key.keysym.scancode) {
|
switch (event.key.keysym.scancode) {
|
||||||
case SDL_SCANCODE_ESCAPE:
|
case SDL_SCANCODE_ESCAPE:
|
||||||
run_gui(true);
|
run_gui(true);
|
||||||
GB_set_color_correction_mode(gb, color_correction_mode);
|
GB_set_color_correction_mode(gb, configuration.color_correction_mode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_SCANCODE_C:
|
case SDL_SCANCODE_C:
|
||||||
@ -142,10 +142,6 @@ static void handle_events(GB_gameboy_t *gb)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_SCANCODE_TAB:
|
|
||||||
cycle_scaling();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Save states */
|
/* Save states */
|
||||||
if (event.key.keysym.scancode >= SDL_SCANCODE_0 && event.key.keysym.scancode <= SDL_SCANCODE_9) {
|
if (event.key.keysym.scancode >= SDL_SCANCODE_0 && event.key.keysym.scancode <= SDL_SCANCODE_9) {
|
||||||
@ -163,34 +159,15 @@ static void handle_events(GB_gameboy_t *gb)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SDL_KEYUP: // Fallthrough
|
case SDL_KEYUP: // Fallthrough
|
||||||
switch (event.key.keysym.scancode) {
|
if (event.key.keysym.scancode == configuration.keys[8]) {
|
||||||
case SDL_SCANCODE_RIGHT:
|
|
||||||
GB_set_key_state(gb, GB_KEY_RIGHT, event.type == SDL_KEYDOWN);
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_LEFT:
|
|
||||||
GB_set_key_state(gb, GB_KEY_LEFT, event.type == SDL_KEYDOWN);
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_UP:
|
|
||||||
GB_set_key_state(gb, GB_KEY_UP, event.type == SDL_KEYDOWN);
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_DOWN:
|
|
||||||
GB_set_key_state(gb, GB_KEY_DOWN, event.type == SDL_KEYDOWN);
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_X:
|
|
||||||
GB_set_key_state(gb, GB_KEY_A, event.type == SDL_KEYDOWN);
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_Z:
|
|
||||||
GB_set_key_state(gb, GB_KEY_B, event.type == SDL_KEYDOWN);
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_BACKSPACE:
|
|
||||||
GB_set_key_state(gb, GB_KEY_SELECT, event.type == SDL_KEYDOWN);
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_RETURN:
|
|
||||||
GB_set_key_state(gb, GB_KEY_START, event.type == SDL_KEYDOWN);
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_SPACE:
|
|
||||||
GB_set_turbo_mode(gb, event.type == SDL_KEYDOWN, false);
|
GB_set_turbo_mode(gb, event.type == SDL_KEYDOWN, false);
|
||||||
break;
|
}
|
||||||
|
else {
|
||||||
|
for (unsigned i = 0; i < GB_KEY_MAX; i++) {
|
||||||
|
if (event.key.keysym.scancode == configuration.keys[i]) {
|
||||||
|
GB_set_key_state(gb, i, event.type == SDL_KEYDOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -297,7 +274,7 @@ restart:
|
|||||||
GB_set_pixels_output(&gb, pixels);
|
GB_set_pixels_output(&gb, pixels);
|
||||||
GB_set_rgb_encode_callback(&gb, rgb_encode);
|
GB_set_rgb_encode_callback(&gb, rgb_encode);
|
||||||
GB_set_sample_rate(&gb, have_aspec.freq);
|
GB_set_sample_rate(&gb, have_aspec.freq);
|
||||||
GB_set_color_correction_mode(&gb, color_correction_mode);
|
GB_set_color_correction_mode(&gb, configuration.color_correction_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user