diff --git a/include/app/app.h b/include/app/app.h index 1f951f2..de9e7ad 100644 --- a/include/app/app.h +++ b/include/app/app.h @@ -162,6 +162,12 @@ struct app { // Skip BIOS bool skip_bios; + // Automatically pause the game when the window looses focus + bool auto_pause; + + // Pause immediately after resetting the game + bool pause_on_reset; + // Backup storage struct { bool autodetect; @@ -424,7 +430,7 @@ void app_config_push_recent_rom(struct app *app, char const *path); /* emulator.c */ void app_emulator_process_all_notifs(struct app *app); -bool app_emulator_configure(struct app *app, char const *rom_path); +bool app_emulator_configure_and_run(struct app *app, char const *rom_path); void app_emulator_reset(struct app *app); void app_emulator_stop(struct app *app); void app_emulator_run(struct app *app); diff --git a/source/app/bindings.c b/source/app/bindings.c index 6d5a2fd..b747d26 100644 --- a/source/app/bindings.c +++ b/source/app/bindings.c @@ -166,7 +166,7 @@ app_bindings_handle( case BIND_EMULATOR_QUICKSAVE: app_emulator_quicksave(app, 0); break; case BIND_EMULATOR_QUICKLOAD: app_emulator_quickload(app, 0); break; case BIND_EMULATOR_PAUSE: app->emulation.is_running ? app_emulator_pause(app) : app_emulator_run(app); break; - case BIND_EMULATOR_RESET: app_emulator_reset(app); app_emulator_run(app); break; + case BIND_EMULATOR_RESET: app_emulator_reset(app); break; default: break; } } diff --git a/source/app/config.c b/source/app/config.c index fb862f1..f3b91c9 100644 --- a/source/app/config.c +++ b/source/app/config.c @@ -94,6 +94,14 @@ app_config_load( if (mjson_get_bool(data, data_len, "$.emulation.skip_bios", &b)) { app->emulation.skip_bios = b; } + + if (mjson_get_bool(data, data_len, "$.emulation.auto_pause", &b)) { + app->emulation.auto_pause = b; + } + + if (mjson_get_bool(data, data_len, "$.emulation.pause_on_reset", &b)) { + app->emulation.pause_on_reset = b; + } } // Video @@ -251,7 +259,9 @@ app_config_save( "rtc": { "autodetect": %B, "enabled": %B - } + }, + "auto_pause": %B, + "pause_on_reset": %B }, // Video @@ -283,6 +293,8 @@ app_config_save( (int)app->emulation.backup_storage.type, (int)app->emulation.rtc.autodetect, (int)app->emulation.rtc.enabled, + (int)app->emulation.auto_pause, + (int)app->emulation.pause_on_reset, (int)app->video.display_size, (int)app->video.aspect_ratio, (int)app->video.vsync, diff --git a/source/app/emulator.c b/source/app/emulator.c index a6340c1..b4a7636 100644 --- a/source/app/emulator.c +++ b/source/app/emulator.c @@ -468,9 +468,10 @@ app_emulator_configure_backup( ** - Update the gba's launch configuration ** - Reset the emulator ** - Wait for the reset notification +** - Run/Pause the emulator, according to the configuration */ bool -app_emulator_configure( +app_emulator_configure_and_run( struct app *app, char const *rom_path ) { @@ -601,6 +602,12 @@ app_emulator_configure( logln(HS_INFO, "Game successfully loaded."); + if (app->emulation.pause_on_reset) { + app_emulator_pause(app); + } else { + app_emulator_run(app); + } + return (false); } @@ -614,7 +621,7 @@ app_emulator_reset( char *game_path; game_path = strdup(app->emulation.game_path); - app_emulator_configure(app, game_path); + app_emulator_configure_and_run(app, game_path); free(game_path); } diff --git a/source/app/main.c b/source/app/main.c index 4c17a2b..53a95ae 100644 --- a/source/app/main.c +++ b/source/app/main.c @@ -117,14 +117,7 @@ main( ); if (app.args.rom_path) { - app_emulator_configure(&app, app.args.rom_path); - if (app.emulation.launch_config) { -#ifdef WITH_DEBUGGER - app_emulator_pause(&app); -#else - app_emulator_run(&app); -#endif - } + app_emulator_configure_and_run(&app, app.args.rom_path); } #ifdef WITH_DEBUGGER diff --git a/source/app/sdl/event.c b/source/app/sdl/event.c index 501c863..c578b7f 100644 --- a/source/app/sdl/event.c +++ b/source/app/sdl/event.c @@ -76,6 +76,18 @@ app_sdl_handle_events( } break; }; + case SDL_WINDOWEVENT_FOCUS_GAINED: { + if (app->emulation.auto_pause && app->emulation.is_started && !app->emulation.is_running) { + app_emulator_run(app); + } + break; + }; + case SDL_WINDOWEVENT_FOCUS_LOST: { + if (app->emulation.auto_pause && app->emulation.is_started && app->emulation.is_running) { + app_emulator_pause(app); + } + break; + }; } break; }; diff --git a/source/app/windows/menubar.c b/source/app/windows/menubar.c index aee73a7..b793d02 100644 --- a/source/app/windows/menubar.c +++ b/source/app/windows/menubar.c @@ -36,9 +36,7 @@ app_win_menubar_file( ); if (result == NFD_OKAY) { - if (!app_emulator_configure(app, path)) { - app_emulator_run(app); - } + app_emulator_configure_and_run(app, path); NFD_FreePath(path); } } @@ -50,13 +48,11 @@ app_win_menubar_file( if (igMenuItem_Bool(hs_basename(app->file.recent_roms[x]), NULL, false, true)) { char *path; - // app->file.recent_roms[] is modified by `app_emulator_configure()` so we need to copy + // app->file.recent_roms[] is modified by `app_emulator_configure_and_run()` so we need to copy // the path to a safe space first. path = strdup(app->file.recent_roms[x]); - if (!app_emulator_configure(app, path)) { - app_emulator_run(app); - } + app_emulator_configure_and_run(app, path); free(path); } @@ -199,7 +195,6 @@ app_win_menubar_emulation( bind = SDL_GetKeyName(app->binds.keyboard[BIND_EMULATOR_RESET]); if (igMenuItem_Bool("Reset", bind ?: "", false, app->emulation.is_started)) { app_emulator_reset(app); - app_emulator_run(app); } igSeparator(); diff --git a/source/app/windows/settings.c b/source/app/windows/settings.c index 143dd2c..f9d1062 100644 --- a/source/app/windows/settings.c +++ b/source/app/windows/settings.c @@ -126,141 +126,163 @@ app_win_settings_emulation( igSeparator(); igSpacing(); - if (igBeginTabBar("##EmulationSettings", ImGuiTabBarFlags_None)) { - if (igBeginTabItem("BIOS", NULL, ImGuiTabItemFlags_None)) { - if (igBeginTable("##EmulationSettingsBIOS", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { - igTableSetupColumn("##EmulationSettingsBIOSLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); - igTableSetupColumn("##EmulationSettingsBIOSValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); - - // BIOS Path - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("BIOS"); - - igTableNextColumn(); - igBeginDisabled(true); - igInputText("##BiosPath", app->file.bios_path, strlen(app->file.bios_path), ImGuiInputTextFlags_ReadOnly, NULL, NULL); - igEndDisabled(); - igSameLine(0.0f, -1.0f); - if (igButton("Choose", (ImVec2){ 50.f, 0.f})) { - nfdresult_t result; - nfdchar_t *path; - - result = NFD_OpenDialog( - &path, - (nfdfilteritem_t[1]){(nfdfilteritem_t){ .name = "BIOS file", .spec = "bin,bios,raw"}}, - 1, - NULL - ); - - if (result == NFD_OKAY) { - free(app->file.bios_path); - app->file.bios_path = strdup(path); - NFD_FreePath(path); - } - } + igSeparatorText("BIOS"); - // Skip BIOS - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Skip BIOS Intro"); + if (igBeginTable("##EmulationSettingsBIOS", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##EmulationSettingsBIOSLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); + igTableSetupColumn("##EmulationSettingsBIOSValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); - igTableNextColumn(); - igCheckbox("##SkipBIOS", &app->emulation.skip_bios); + // BIOS Path + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("BIOS Path"); - igEndTable(); + igTableNextColumn(); + igBeginDisabled(true); + igInputText("##BiosPath", app->file.bios_path, strlen(app->file.bios_path), ImGuiInputTextFlags_ReadOnly, NULL, NULL); + igEndDisabled(); + igSameLine(0.0f, -1.0f); + if (igButton("Choose", (ImVec2){ 50.f, 0.f})) { + nfdresult_t result; + nfdchar_t *path; + + result = NFD_OpenDialog( + &path, + (nfdfilteritem_t[1]){(nfdfilteritem_t){ .name = "BIOS file", .spec = "bin,bios,raw"}}, + 1, + NULL + ); + + if (result == NFD_OKAY) { + free(app->file.bios_path); + app->file.bios_path = strdup(path); + NFD_FreePath(path); } - igEndTabItem(); } - if (igBeginTabItem("Speed", NULL, ImGuiTabItemFlags_None)) { - if (igBeginTable("##EmulationSettingsSpeed", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { - igTableSetupColumn("##EmulationSettingsSpeedLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); - igTableSetupColumn("##EmulationSettingsSpeedValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); - - // Unbounded Speed - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Unbounded Speed"); - - igTableNextColumn(); - if (igCheckbox("##UnboundedSpeed", &app->emulation.unbounded)) { - app_emulator_speed(app, app->emulation.unbounded ? 0 : app->emulation.speed); - } - // Speed - igBeginDisabled(app->emulation.unbounded); - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Speed"); - - igTableNextColumn(); - if (igCombo_Str_arr("##Speed", &speed, speed_names, array_length(speed_names), 0)) { - app->emulation.speed = speed + 1; - app->emulation.unbounded = false; - app_emulator_speed(app, app->emulation.speed); - } + // Skip BIOS + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Skip BIOS Intro"); - igEndDisabled(); + igTableNextColumn(); + igCheckbox("##SkipBIOS", &app->emulation.skip_bios); - igEndTable(); - } - igEndTabItem(); - } - if (igBeginTabItem("Save", NULL, ImGuiTabItemFlags_None)) { - if (igBeginTable("##EmulationSettingsSave", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { - igTableSetupColumn("##EmulationSettingsSaveLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); - igTableSetupColumn("##EmulationSettingsSaveValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); + igEndTable(); + } - // Unbounded Speed - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Backup Storage Type Auto-Detect"); + igSeparatorText("Speed"); - igTableNextColumn(); - igCheckbox("##BackupStorageTypeAutoDetect", &app->emulation.backup_storage.autodetect); + if (igBeginTable("##EmulationSettingsSpeed", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##EmulationSettingsSpeedLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); + igTableSetupColumn("##EmulationSettingsSpeedValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); - // Backup Storage Type - igBeginDisabled(app->emulation.backup_storage.autodetect); - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Backup Storage Type"); + // Unbounded Speed + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Unbounded Speed"); - igTableNextColumn(); - igCombo_Str_arr("##BackupStorageType", (int *)&app->emulation.backup_storage.type, backup_storage_names, array_length(backup_storage_names), 0); - igEndDisabled(); + igTableNextColumn(); + if (igCheckbox("##UnboundedSpeed", &app->emulation.unbounded)) { + app_emulator_speed(app, app->emulation.unbounded ? 0 : app->emulation.speed); + } - igEndTable(); - } - igEndTabItem(); + // Speed + igBeginDisabled(app->emulation.unbounded); + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Speed"); + + igTableNextColumn(); + if (igCombo_Str_arr("##Speed", &speed, speed_names, array_length(speed_names), 0)) { + app->emulation.speed = speed + 1; + app->emulation.unbounded = false; + app_emulator_speed(app, app->emulation.speed); } - if (igBeginTabItem("Devices", NULL, ImGuiTabItemFlags_None)) { - if (igBeginTable("##EmulationSettingsDevice", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { - igTableSetupColumn("##EmulationSettingsDeviceLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); - igTableSetupColumn("##EmulationSettingsDeviceValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); + igEndDisabled(); + + igEndTable(); + } - // RTC Auto-Detect - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("RTC Auto-Detect"); + igSeparatorText("Backup Storage"); - igTableNextColumn(); - igCheckbox("##RTCAutoDetect", &app->emulation.rtc.autodetect); + if (igBeginTable("##EmulationSettingsBackupStorage", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##EmulationSettingsBackupStorageLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); + igTableSetupColumn("##EmulationSettingsBackupStorageValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); - // RTC Enable - igBeginDisabled(app->emulation.rtc.autodetect); - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("RTC Enable"); + // Backup Storage Auto-Detect + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Auto-Detect"); - igTableNextColumn(); - igCheckbox("##RTCEnable", &app->emulation.rtc.enabled); - igEndDisabled(); + igTableNextColumn(); + igCheckbox("##BackupStorageTypeAutoDetect", &app->emulation.backup_storage.autodetect); - igEndTable(); - } - igEndTabItem(); - } - igEndTabBar(); + // Backup Storage Type + igBeginDisabled(app->emulation.backup_storage.autodetect); + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Type"); + + igTableNextColumn(); + igCombo_Str_arr("##BackupStorageType", (int *)&app->emulation.backup_storage.type, backup_storage_names, array_length(backup_storage_names), 0); + igEndDisabled(); + + igEndTable(); + } + + igSeparatorText("GPIO Devices"); + + if (igBeginTable("##EmulationSettingsGPIODevices", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##EmulationSettingsGPIODevicesLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); + igTableSetupColumn("##EmulationSettingsGPIODevicesValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); + + // RTC Auto-Detect + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("RTC Auto-Detect"); + + igTableNextColumn(); + igCheckbox("##RTCAutoDetect", &app->emulation.rtc.autodetect); + + // RTC Enable + igBeginDisabled(app->emulation.rtc.autodetect); + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("RTC Enable"); + + igTableNextColumn(); + igCheckbox("##RTCEnable", &app->emulation.rtc.enabled); + igEndDisabled(); + + igEndTable(); + } + + igSeparatorText("Misc"); + + if (igBeginTable("##EmulationSettingsMisc", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##EmulationSettingsMiscLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); + igTableSetupColumn("##EmulationSettingsMiscValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); + + // Pause game when the window loses focus + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Auto-Pause"); + + igTableNextColumn(); + igCheckbox("##AutoPause", &app->emulation.auto_pause); + +#ifdef WITH_DEBUGGER + // Pause game after a reset + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Pause Game After Reset"); + + igTableNextColumn(); + igCheckbox("##PauseGameAfterReset", &app->emulation.pause_on_reset); +#endif + + igEndTable(); } } @@ -280,114 +302,110 @@ app_win_settings_video( igSeparator(); igSpacing(); - if (igBeginTabBar("##VideoSettings", ImGuiTabBarFlags_None)) { - if (igBeginTabItem("Display", NULL, ImGuiTabItemFlags_None)) { - if (igBeginTable("##VideoSettingsDisplay", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { - igTableSetupColumn("##VideoSettingsDisplayLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); - igTableSetupColumn("##VideoSettingsDisplayValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); + igSeparatorText("Display"); - // VSync - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("VSync"); + if (igBeginTable("##VideoSettingsDisplay", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##VideoSettingsDisplayLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); + igTableSetupColumn("##VideoSettingsDisplayValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); - igTableNextColumn(); - if (igCheckbox("##VSync", &app->video.vsync)) { - SDL_GL_SetSwapInterval(app->video.vsync); - } + // VSync + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("VSync"); - // Display Size - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Display Size"); + igTableNextColumn(); + if (igCheckbox("##VSync", &app->video.vsync)) { + SDL_GL_SetSwapInterval(app->video.vsync); + } - igTableNextColumn(); + // Display Size + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Display Size"); - display_size = -1; - for (i = 1; i < array_length(display_size_names) + 1; ++i) { - if (vp->WorkSize.x == GBA_SCREEN_WIDTH * i * app->ui.scale && vp->WorkSize.y == GBA_SCREEN_HEIGHT * i * app->ui.scale) { - display_size = i; - break; - } - } + igTableNextColumn(); - if (igBeginCombo("##DisplaySize", display_size > 0 ? display_size_names[display_size - 1] : "", ImGuiComboFlags_None)) { - for (i = 1; i < array_length(display_size_names) + 1; ++i) { - bool is_selected; - - is_selected = (display_size == i); - if (igSelectable_Bool(display_size_names[i - 1], is_selected, ImGuiSelectableFlags_None, (ImVec2){ 0.f, 0.f })) { - app->video.display_size = i; - app->ui.win.resize = true; - app->ui.win.resize_with_ratio = false; - } - - if (is_selected) { - igSetItemDefaultFocus(); - } - } - igEndCombo(); + display_size = -1; + for (i = 1; i < array_length(display_size_names) + 1; ++i) { + if (vp->WorkSize.x == GBA_SCREEN_WIDTH * i * app->ui.scale && vp->WorkSize.y == GBA_SCREEN_HEIGHT * i * app->ui.scale) { + display_size = i; + break; + } + } + + if (igBeginCombo("##DisplaySize", display_size > 0 ? display_size_names[display_size - 1] : "", ImGuiComboFlags_None)) { + for (i = 1; i < array_length(display_size_names) + 1; ++i) { + bool is_selected; + + is_selected = (display_size == i); + if (igSelectable_Bool(display_size_names[i - 1], is_selected, ImGuiSelectableFlags_None, (ImVec2){ 0.f, 0.f })) { + app->video.display_size = i; + app->ui.win.resize = true; + app->ui.win.resize_with_ratio = false; } - // Aspect Ratio - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Aspect Ratio"); - - igTableNextColumn(); - if (igCombo_Str_arr("##AspectRatio", (int *)&app->video.aspect_ratio, aspect_ratio_names, ASPECT_RATIO_LEN, 0)) { - // Force a resize of the window if the "auto-resize" option is selected - if (app->video.aspect_ratio == ASPECT_RATIO_RESIZE) { - app->ui.win.resize = true; - app->ui.win.resize_with_ratio = true; - app->ui.win.resize_ratio = min(app->ui.game.width / ((float)GBA_SCREEN_WIDTH * app->ui.scale), app->ui.game.height / ((float)GBA_SCREEN_HEIGHT * app->ui.scale)); - } + if (is_selected) { + igSetItemDefaultFocus(); } + } + igEndCombo(); + } - igEndTable(); + // Aspect Ratio + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Aspect Ratio"); + + igTableNextColumn(); + if (igCombo_Str_arr("##AspectRatio", (int *)&app->video.aspect_ratio, aspect_ratio_names, ASPECT_RATIO_LEN, 0)) { + // Force a resize of the window if the "auto-resize" option is selected + if (app->video.aspect_ratio == ASPECT_RATIO_RESIZE) { + app->ui.win.resize = true; + app->ui.win.resize_with_ratio = true; + app->ui.win.resize_ratio = min(app->ui.game.width / ((float)GBA_SCREEN_WIDTH * app->ui.scale), app->ui.game.height / ((float)GBA_SCREEN_HEIGHT * app->ui.scale)); } - igEndTabItem(); } - if (igBeginTabItem("Filters", NULL, ImGuiTabItemFlags_None)) { - if (igBeginTable("##VideoSettingsFilters", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { - igTableSetupColumn("##VideoSettingsFiltersLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); - igTableSetupColumn("##VideoSettingsFiltersValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); - - // Texture Filter - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Texture Filter"); - - igTableNextColumn(); - if (igCombo_Str_arr("##TextureFilters", (int *)&app->video.texture_filter, texture_filters_names, TEXTURE_FILTER_LEN, 0)) { - app_sdl_video_rebuild_pipeline(app); - } - // Color Filter - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Color Filter"); + igEndTable(); + } - igTableNextColumn(); - if (igCombo_Str_arr("##ColorFilter", (int *)&app->video.pixel_color_filter, pixel_color_filters_names, PIXEL_COLOR_FILTER_LEN, 0)) { - app_sdl_video_rebuild_pipeline(app); - } + igSeparatorText("Filters"); - // Scaling Filter - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - igTableNextColumn(); - igTextWrapped("Scaling Filter"); + if (igBeginTable("##VideoSettingsFilters", 2, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##VideoSettingsFiltersLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0); + igTableSetupColumn("##VideoSettingsFiltersValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0); - igTableNextColumn(); - if (igCombo_Str_arr("##ScalingFilter", (int *)&app->video.pixel_scaling_filter, pixel_scaling_filters_names, PIXEL_SCALING_FILTER_LEN, 0)) { - app_sdl_video_rebuild_pipeline(app); - } + // Texture Filter + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Texture Filter"); - igEndTable(); - } - igEndTabItem(); + igTableNextColumn(); + if (igCombo_Str_arr("##TextureFilters", (int *)&app->video.texture_filter, texture_filters_names, TEXTURE_FILTER_LEN, 0)) { + app_sdl_video_rebuild_pipeline(app); } - igEndTabBar(); + + // Color Filter + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Color Filter"); + + igTableNextColumn(); + if (igCombo_Str_arr("##ColorFilter", (int *)&app->video.pixel_color_filter, pixel_color_filters_names, PIXEL_COLOR_FILTER_LEN, 0)) { + app_sdl_video_rebuild_pipeline(app); + } + + // Scaling Filter + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + igTableNextColumn(); + igTextWrapped("Scaling Filter"); + + igTableNextColumn(); + if (igCombo_Str_arr("##ScalingFilter", (int *)&app->video.pixel_scaling_filter, pixel_scaling_filters_names, PIXEL_SCALING_FILTER_LEN, 0)) { + app_sdl_video_rebuild_pipeline(app); + } + + igEndTable(); } } @@ -435,6 +453,74 @@ app_win_settings_audio( } } +static +void +app_win_settings_bindings_bind_keyboard( + struct app *app, + size_t bind +) { + SDL_Keycode *keycode; + char const *name; + char label[128]; + size_t j; + + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + + igTableNextColumn(); + igTextWrapped(binds_pretty_name[bind]); + + for (j = 0; j < 2; ++j) { + keycode = (j == 0) ? &app->binds.keyboard[bind] : &app->binds.keyboard_alt[bind]; + name = SDL_GetKeyName(*keycode); + + if (keycode == app->ui.settings.keybindings_editor.keyboard_target) { + snprintf(label, sizeof(label), ">> %s <<##BindingsSettingsKeyboard%zu", name ?: " ", bind * 10 + j); + } else { + snprintf(label, sizeof(label), "%s##BindingsSettingsKeyboard%zu", name ?: "", bind * 10 + j); + } + + igTableNextColumn(); + if (igButton(label, (ImVec2){ -1.f, 0.f })) { + app->ui.settings.keybindings_editor.keyboard_target = keycode; + app->ui.settings.keybindings_editor.controller_target = NULL; + } + } +} + +static +void +app_win_settings_bindings_bind_controller( + struct app *app, + size_t bind +) { + SDL_GameControllerButton *button; + char const *name; + char label[128]; + size_t j; + + igTableNextRow(ImGuiTableRowFlags_None, 0.f); + + igTableNextColumn(); + igTextWrapped(binds_pretty_name[bind]); + + for (j = 0; j < 2; ++j) { + button = (j == 0) ? &app->binds.controller[bind] : &app->binds.controller_alt[bind]; + name = SDL_GameControllerGetStringForButton(*button); + + if (button == app->ui.settings.keybindings_editor.controller_target) { + snprintf(label, sizeof(label), ">> %s <<##BindingsSettingsController%zu", name ?: " ", bind * 10 + j); + } else { + snprintf(label, sizeof(label), "%s##BindingsSettingsController%zu", name ?: "", bind * 10 + j); + } + + igTableNextColumn(); + if (igButton(label, (ImVec2){ -1.f, 0.f })) { + app->ui.settings.keybindings_editor.controller_target = button; + app->ui.settings.keybindings_editor.keyboard_target = NULL; + } + } +} + static void app_win_settings_bindings( @@ -449,81 +535,65 @@ app_win_settings_bindings( if (igBeginTabBar("##BindingsSettings", ImGuiTabBarFlags_None)) { if (igBeginTabItem("Keyboard", NULL, ImGuiTabItemFlags_None)) { - if (igBeginTable("##BindingsSettingsKeyboard", 3, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { - igTableSetupColumn("##BindingsSettingsKeyboardLabel", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); - igTableSetupColumn("##BindingsSettingsKeyboardBindMain", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); - igTableSetupColumn("##BindingsSettingsKeyboardBindAlt", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); - - for (bind = BIND_MIN; bind < BIND_MAX; ++bind) { - size_t j; - - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - - igTableNextColumn(); - igTextWrapped(binds_pretty_name[bind]); - - for (j = 0; j < 2; ++j) { - SDL_Keycode *keycode; - char const *name; - char label[128]; - - keycode = (j == 0) ? &app->binds.keyboard[bind] : &app->binds.keyboard_alt[bind]; - name = SDL_GetKeyName(*keycode); - - if (keycode == app->ui.settings.keybindings_editor.keyboard_target) { - snprintf(label, sizeof(label), ">> %s <<##BindingsSettingsKeyboard%zu", name ?: " ", bind * 10 + j); - } else { - snprintf(label, sizeof(label), "%s##BindingsSettingsKeyboard%zu", name ?: "", bind * 10 + j); - } - - igTableNextColumn(); - if (igButton(label, (ImVec2){ -1.f, 0.f })) { - app->ui.settings.keybindings_editor.keyboard_target = keycode; - app->ui.settings.keybindings_editor.controller_target = NULL; - } - } + + igSeparatorText("GBA"); + + if (igBeginTable("##BindingsSettingsKeyboardGBA", 3, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##BindingsSettingsKeyboardGBALabel", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + igTableSetupColumn("##BindingsSettingsKeyboardGBABindMain", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + igTableSetupColumn("##BindingsSettingsKeyboardGBABindAlt", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + + for (bind = BIND_GBA_MIN; bind <= BIND_GBA_MAX; ++bind) { + app_win_settings_bindings_bind_keyboard(app, bind); } + igEndTable(); } + + igSeparatorText("Emulator"); + + if (igBeginTable("##BindingsSettingsKeyboardEmulator", 3, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##BindingsSettingsKeyboardEmulatorLabel", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + igTableSetupColumn("##BindingsSettingsKeyboardEmulatorBindMain", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + igTableSetupColumn("##BindingsSettingsKeyboardEmulatorBindAlt", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + + for (bind = BIND_EMULATOR_MIN; bind <= BIND_EMULATOR_MAX; ++bind) { + app_win_settings_bindings_bind_keyboard(app, bind); + } + igEndTable(); + } + igEndTabItem(); } if (igBeginTabItem("Controller", NULL, ImGuiTabItemFlags_None)) { - if (igBeginTable("##BindingsSettingsController", 3, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { - igTableSetupColumn("##BindingsSettingsControllerLabel", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); - igTableSetupColumn("##BindingsSettingsControllerBindMain", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); - igTableSetupColumn("##BindingsSettingsControllerBindAlt", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); - - for (bind = BIND_MIN; bind < BIND_MAX; ++bind) { - size_t j; - - igTableNextRow(ImGuiTableRowFlags_None, 0.f); - - igTableNextColumn(); - igTextWrapped(binds_pretty_name[bind]); - - for (j = 0; j < 2; ++j) { - SDL_GameControllerButton *button; - char const *name; - char label[128]; - - button = (j == 0) ? &app->binds.controller[bind] : &app->binds.controller_alt[bind]; - name = SDL_GameControllerGetStringForButton(*button); - - if (button == app->ui.settings.keybindings_editor.controller_target) { - snprintf(label, sizeof(label), ">> %s <<##BindingsSettingsController%zu", name ?: " ", bind * 10 + j); - } else { - snprintf(label, sizeof(label), "%s##BindingsSettingsController%zu", name ?: "", bind * 10 + j); - } - - igTableNextColumn(); - if (igButton(label, (ImVec2){ -1.f, 0.f })) { - app->ui.settings.keybindings_editor.controller_target = button; - app->ui.settings.keybindings_editor.keyboard_target = NULL; - } - } + + igSeparatorText("GBA"); + + if (igBeginTable("##BindingsSettingsControllerGBA", 3, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##BindingsSettingsControllerGBALabel", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + igTableSetupColumn("##BindingsSettingsControllerGBABindMain", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + igTableSetupColumn("##BindingsSettingsControllerGBABindAlt", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + + for (bind = BIND_GBA_MIN; bind <= BIND_GBA_MAX; ++bind) { + app_win_settings_bindings_bind_controller(app, bind); } + igEndTable(); } + + igSeparatorText("Emulator"); + + if (igBeginTable("##BindingsSettingsControllerEmulator", 3, ImGuiTableFlags_None, (ImVec2){ .x = 0.f, .y = 0.f }, 0.f)) { + igTableSetupColumn("##BindingsSettingsControllerEmulatorLabel", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + igTableSetupColumn("##BindingsSettingsControllerEmulatorBindMain", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + igTableSetupColumn("##BindingsSettingsControllerEmulatorBindAlt", ImGuiTableColumnFlags_WidthStretch, 1.f, 0); + + for (bind = BIND_EMULATOR_MIN; bind <= BIND_EMULATOR_MAX; ++bind) { + app_win_settings_bindings_bind_controller(app, bind); + } + igEndTable(); + } + igEndTabItem(); } igEndTabBar();