summaryrefslogtreecommitdiffstats
path: root/gearboy/platforms/desktop-shared/gui.cpp
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2022-06-02 15:28:40 +0200
committerLouis Burda <quent.burda@gmail.com>2022-06-02 15:28:40 +0200
commit5bc16063c29aa4d3d287ebd163ccdbcbf54c4f9f (patch)
treec131f947a37b3af2d14d41e9eda098bdec2d061c /gearboy/platforms/desktop-shared/gui.cpp
parent78a5f810b22f0d8cafa05f638b0cb2e889824859 (diff)
downloadcscg2022-gearboy-master.tar.gz
cscg2022-gearboy-master.zip
Added submodule filesHEADmaster
Diffstat (limited to 'gearboy/platforms/desktop-shared/gui.cpp')
-rw-r--r--gearboy/platforms/desktop-shared/gui.cpp1446
1 files changed, 1446 insertions, 0 deletions
diff --git a/gearboy/platforms/desktop-shared/gui.cpp b/gearboy/platforms/desktop-shared/gui.cpp
new file mode 100644
index 00000000..6e5a671b
--- /dev/null
+++ b/gearboy/platforms/desktop-shared/gui.cpp
@@ -0,0 +1,1446 @@
+/*
+ * Gearboy - Nintendo Game Boy Emulator
+ * Copyright (C) 2012 Ignacio Sanchez
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/
+ *
+ */
+
+#include "imgui/imgui.h"
+#include "imgui/imgui_memory_editor.h"
+#include "imgui/fonts/RobotoMedium.h"
+#include "FileBrowser/ImGuiFileBrowser.h"
+#include "config.h"
+#include "emu.h"
+#include "../../src/gearboy.h"
+#include "renderer.h"
+#include "application.h"
+#include "license.h"
+#include "backers.h"
+#include "gui_debug.h"
+
+#define GUI_IMPORT
+#include "gui.h"
+
+static imgui_addons::ImGuiFileBrowser file_dialog;
+static int main_menu_height;
+static bool dialog_in_use = false;
+static SDL_Scancode* configured_key;
+static int* configured_button;
+static ImVec4 custom_palette[config_max_custom_palettes][4];
+static std::list<std::string> cheat_list;
+static bool shortcut_open_rom = false;
+static ImFont* default_font[4];
+static char dmg_bootrom_path[4096] = "";
+static char gbc_bootrom_path[4096] = "";
+static char savefiles_path[4096] = "";
+static char savestates_path[4096] = "";
+static bool show_main_menu = true;
+
+static void main_menu(void);
+static void main_window(void);
+static void file_dialog_open_rom(void);
+static void file_dialog_load_ram(void);
+static void file_dialog_save_ram(void);
+static void file_dialog_load_state(void);
+static void file_dialog_save_state(void);
+static void file_dialog_choose_save_file_path(void);
+static void file_dialog_choose_savestate_path(void);
+static void file_dialog_load_dmg_bootrom(void);
+static void file_dialog_load_gbc_bootrom(void);
+static void file_dialog_load_symbols(void);
+static void keyboard_configuration_item(const char* text, SDL_Scancode* key);
+static void gamepad_configuration_item(const char* text, int* button);
+static void popup_modal_keyboard(void);
+static void popup_modal_gamepad(void);
+static void popup_modal_about(void);
+static GB_Color color_float_to_int(ImVec4 color);
+static ImVec4 color_int_to_float(GB_Color color);
+static void update_palette(void);
+static void push_recent_rom(std::string path);
+static void menu_reset(void);
+static void menu_pause(void);
+static void menu_ffwd(void);
+static void show_info(void);
+static void show_fps(void);
+static Cartridge::CartridgeTypes get_mbc(int index);
+
+void gui_init(void)
+{
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGui::StyleColorsDark();
+ ImGuiIO& io = ImGui::GetIO();
+
+ io.IniFilename = config_imgui_file_path;
+
+ io.FontGlobalScale /= application_display_scale;
+
+ gui_roboto_font = io.Fonts->AddFontFromMemoryCompressedTTF(RobotoMedium_compressed_data, RobotoMedium_compressed_size, 17.0f * application_display_scale, NULL, io.Fonts->GetGlyphRangesCyrillic());
+
+ ImFontConfig font_cfg;
+
+ for (int i = 0; i < 4; i++)
+ {
+ font_cfg.SizePixels = (13.0f + (i * 3)) * application_display_scale;
+ default_font[i] = io.Fonts->AddFontDefault(&font_cfg);
+ }
+
+ gui_default_font = default_font[config_debug.font_size];
+
+ update_palette();
+
+ emu_audio_volume(config_audio.enable ? 1.0f: 0.0f);
+ emu_color_correction(config_video.color_correction);
+
+ strcpy(dmg_bootrom_path, config_emulator.dmg_bootrom_path.c_str());
+ strcpy(gbc_bootrom_path, config_emulator.gbc_bootrom_path.c_str());
+ strcpy(savefiles_path, config_emulator.savefiles_path.c_str());
+ strcpy(savestates_path, config_emulator.savestates_path.c_str());
+
+ if (strlen(dmg_bootrom_path) > 0)
+ emu_load_bootrom_dmg(dmg_bootrom_path);
+ if (strlen(gbc_bootrom_path) > 0)
+ emu_load_bootrom_gbc(gbc_bootrom_path);
+
+ emu_enable_bootrom_dmg(config_emulator.dmg_bootrom);
+ emu_enable_bootrom_gbc(config_emulator.gbc_bootrom);
+}
+
+void gui_destroy(void)
+{
+ ImGui::DestroyContext();
+}
+
+void gui_render(void)
+{
+ ImGui::NewFrame();
+
+ gui_in_use = dialog_in_use;
+
+ main_menu();
+
+ if((!config_debug.debug && !emu_is_empty()) || (config_debug.debug && config_debug.show_gameboy))
+ main_window();
+
+ gui_debug_windows();
+
+ ImGui::Render();
+}
+
+void gui_shortcut(gui_ShortCutEvent event)
+{
+ switch (event)
+ {
+ case gui_ShortcutOpenROM:
+ shortcut_open_rom = true;
+ break;
+ case gui_ShortcutReset:
+ menu_reset();
+ break;
+ case gui_ShortcutPause:
+ menu_pause();
+ break;
+ case gui_ShortcutFFWD:
+ config_emulator.ffwd = !config_emulator.ffwd;
+ menu_ffwd();
+ break;
+ case gui_ShortcutSaveState:
+ emu_save_state_slot(config_emulator.save_slot + 1);
+ break;
+ case gui_ShortcutLoadState:
+ emu_load_state_slot(config_emulator.save_slot + 1);
+ break;
+ case gui_ShortcutDebugStep:
+ if (config_debug.debug)
+ emu_debug_step();
+ break;
+ case gui_ShortcutDebugContinue:
+ if (config_debug.debug)
+ emu_debug_continue();
+ break;
+ case gui_ShortcutDebugNextFrame:
+ if (config_debug.debug)
+ emu_debug_next_frame();
+ break;
+ case gui_ShortcutDebugBreakpoint:
+ if (config_debug.debug)
+ gui_debug_toggle_breakpoint();
+ break;
+ case gui_ShortcutDebugRuntocursor:
+ if (config_debug.debug)
+ gui_debug_runtocursor();
+ break;
+ case gui_ShortcutDebugGoBack:
+ if (config_debug.debug)
+ gui_debug_go_back();
+ break;
+ case gui_ShortcutShowMainMenu:
+ show_main_menu = !show_main_menu;
+ break;
+ default:
+ break;
+ }
+}
+
+void gui_load_rom(const char* path)
+{
+ push_recent_rom(path);
+ emu_resume();
+ emu_load_rom(path, config_emulator.force_dmg, get_mbc(config_emulator.mbc), config_emulator.force_gba);
+ cheat_list.clear();
+ emu_clear_cheats();
+
+ gui_debug_reset();
+
+ std::string str(path);
+ str = str.substr(0, str.find_last_of("."));
+ str += ".sym";
+ gui_debug_load_symbols_file(str.c_str());
+
+ if (config_emulator.start_paused)
+ {
+ emu_pause();
+
+ for (int i=0; i < (GAMEBOY_WIDTH * GAMEBOY_HEIGHT); i++)
+ {
+ emu_frame_buffer[i].red = 0;
+ emu_frame_buffer[i].green = 0;
+ emu_frame_buffer[i].blue = 0;
+ }
+ }
+}
+
+static void main_menu(void)
+{
+ bool open_rom = false;
+ bool open_ram = false;
+ bool save_ram = false;
+ bool open_state = false;
+ bool save_state = false;
+ bool open_about = false;
+ bool open_symbols = false;
+ bool choose_save_file_path = false;
+ bool choose_savestates_path = false;
+ bool open_dmg_bootrom = false;
+ bool open_gbc_bootrom = false;
+
+ for (int i = 0; i < config_max_custom_palettes; i++)
+ for (int c = 0; c < 4; c++)
+ custom_palette[i][c] = color_int_to_float(config_video.color[i][c]);
+
+ if (show_main_menu && ImGui::BeginMainMenuBar())
+ {
+ if (ImGui::BeginMenu(GEARBOY_TITLE))
+ {
+ gui_in_use = true;
+
+ if (ImGui::MenuItem("Open ROM...", "Ctrl+O"))
+ {
+ open_rom = true;
+ }
+
+ if (ImGui::BeginMenu("Open Recent"))
+ {
+ for (int i = 0; i < config_max_recent_roms; i++)
+ {
+ if (config_emulator.recent_roms[i].length() > 0)
+ {
+ if (ImGui::MenuItem(config_emulator.recent_roms[i].c_str()))
+ {
+ char rom_path[4096];
+ strcpy(rom_path, config_emulator.recent_roms[i].c_str());
+ gui_load_rom(rom_path);
+ }
+ }
+ }
+
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Reset", "Ctrl+R"))
+ {
+ menu_reset();
+ }
+
+ if (ImGui::MenuItem("Pause", "Ctrl+P", &config_emulator.paused))
+ {
+ menu_pause();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Fast Forward", "Ctrl+F", &config_emulator.ffwd))
+ {
+ menu_ffwd();
+ }
+
+ if (ImGui::BeginMenu("Fast Forward Speed"))
+ {
+ ImGui::PushItemWidth(100.0f);
+ ImGui::Combo("##fwd", &config_emulator.ffwd_speed, "X 1.5\0X 2\0X 2.5\0X 3\0Unlimited\0\0");
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Save RAM As..."))
+ {
+ save_ram = true;
+ }
+
+ if (ImGui::MenuItem("Load RAM From..."))
+ {
+ open_ram = true;
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Save State As..."))
+ {
+ save_state = true;
+ }
+
+ if (ImGui::MenuItem("Load State From..."))
+ {
+ open_state = true;
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::BeginMenu("Save State Slot"))
+ {
+ ImGui::PushItemWidth(100.0f);
+ ImGui::Combo("##slot", &config_emulator.save_slot, "Slot 1\0Slot 2\0Slot 3\0Slot 4\0Slot 5\0\0");
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::MenuItem("Save State", "Ctrl+S"))
+ {
+ emu_save_state_slot(config_emulator.save_slot + 1);
+ }
+
+ if (ImGui::MenuItem("Load State", "Ctrl+L"))
+ {
+ emu_load_state_slot(config_emulator.save_slot + 1);
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Quit", "ESC"))
+ {
+ application_trigger_quit();
+ }
+
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Emulator"))
+ {
+ gui_in_use = true;
+
+ if (ImGui::MenuItem("Force Game Boy (DMG)", "", &config_emulator.force_dmg))
+ {
+ if (config_emulator.force_dmg)
+ config_emulator.force_gba = false;
+ }
+
+ if (ImGui::MenuItem("Force Game Boy Advance", "", &config_emulator.force_gba))
+ {
+ if (config_emulator.force_gba)
+ config_emulator.force_dmg = false;
+ }
+
+ if (ImGui::BeginMenu("Memory Bank Controller"))
+ {
+ ImGui::PushItemWidth(140.0f);
+ ImGui::Combo("##mbc", &config_emulator.mbc, "Auto\0ROM Only\0MBC 1\0MBC 2\0MBC 3\0MBC 5\0MBC 1 Multicart\0\0");
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::BeginMenu("DMG Bootrom"))
+ {
+ if (ImGui::MenuItem("Enable", "", &config_emulator.dmg_bootrom))
+ {
+ emu_enable_bootrom_dmg(config_emulator.dmg_bootrom);
+ }
+ if (ImGui::IsItemHovered())
+ ImGui::SetTooltip("When the bootrom is enabled it will execute as in original hardware,\ncausing invalid roms to lock or forcing hardware like GB Pocket or GBA.");
+ if (ImGui::MenuItem("Load Bootrom..."))
+ {
+ open_dmg_bootrom = true;
+ }
+ ImGui::PushItemWidth(350);
+ if (ImGui::InputText("##dmg_bootrom_path", dmg_bootrom_path, IM_ARRAYSIZE(dmg_bootrom_path), ImGuiInputTextFlags_AutoSelectAll))
+ {
+ config_emulator.dmg_bootrom_path.assign(dmg_bootrom_path);
+ emu_load_bootrom_dmg(dmg_bootrom_path);
+ }
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("GBC Bootrom"))
+ {
+ if (ImGui::MenuItem("Enable", "", &config_emulator.gbc_bootrom))
+ {
+ emu_enable_bootrom_gbc(config_emulator.gbc_bootrom);
+ }
+ if (ImGui::IsItemHovered())
+ ImGui::SetTooltip("When the bootrom is enabled it will execute as in original hardware,\ncausing invalid roms to lock or forcing hardware like GB Pocket or GBA.");
+ if (ImGui::MenuItem("Load Bootrom..."))
+ {
+ open_gbc_bootrom = true;
+ }
+ ImGui::PushItemWidth(350);
+ if (ImGui::InputText("##gbc_bootrom_path", gbc_bootrom_path, IM_ARRAYSIZE(gbc_bootrom_path), ImGuiInputTextFlags_AutoSelectAll))
+ {
+ config_emulator.gbc_bootrom_path.assign(gbc_bootrom_path);
+ emu_load_bootrom_gbc(gbc_bootrom_path);
+ }
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+
+ ImGui::MenuItem("Start Paused", "", &config_emulator.start_paused);
+
+ ImGui::Separator();
+
+ if (ImGui::BeginMenu("Save File Location"))
+ {
+ ImGui::PushItemWidth(220.0f);
+ if (ImGui::Combo("##savefile_option", &config_emulator.savefiles_dir_option, "Save Files In Custom Folder\0Save Files In ROM Folder\0\0"))
+ {
+ emu_savefiles_dir_option = config_emulator.savefiles_dir_option;
+ }
+
+ if (config_emulator.savefiles_dir_option == 0)
+ {
+ if (ImGui::MenuItem("Choose Save File Folder..."))
+ {
+ choose_save_file_path = true;
+ }
+
+ ImGui::PushItemWidth(350);
+ if (ImGui::InputText("##savefile_path", savefiles_path, IM_ARRAYSIZE(savefiles_path), ImGuiInputTextFlags_AutoSelectAll))
+ {
+ config_emulator.savefiles_path.assign(savefiles_path);
+ strcpy(emu_savefiles_path, savefiles_path);
+ }
+ ImGui::PopItemWidth();
+ }
+
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Save State Location"))
+ {
+ ImGui::PushItemWidth(220.0f);
+ if (ImGui::Combo("##savestate_option", &config_emulator.savestates_dir_option, "Savestates In Custom Folder\0Savestates In ROM Folder\0\0"))
+ {
+ emu_savestates_dir_option = config_emulator.savestates_dir_option;
+ }
+
+ if (config_emulator.savestates_dir_option == 0)
+ {
+ if (ImGui::MenuItem("Choose Savestate Folder..."))
+ {
+ choose_savestates_path = true;
+ }
+
+ ImGui::PushItemWidth(350);
+ if (ImGui::InputText("##savestate_path", savestates_path, IM_ARRAYSIZE(savestates_path), ImGuiInputTextFlags_AutoSelectAll))
+ {
+ config_emulator.savestates_path.assign(savestates_path);
+ strcpy(emu_savestates_path, savestates_path);
+ }
+ ImGui::PopItemWidth();
+ }
+
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+
+ ImGui::MenuItem("Show ROM info", "", &config_emulator.show_info);
+
+ ImGui::Separator();
+
+ ImGui::SetNextWindowSizeConstraints({300.0f, 200.0f}, {300.0f, 500.0f});
+ if (ImGui::BeginMenu("Cheats"))
+ {
+ ImGui::Text("Game Genie or GameShark codes\n(one code per line):");
+
+ ImGui::Columns(2, "cheats", false);
+
+ static char cheat_buffer[20*50] = "";
+ ImGui::PushItemWidth(150);
+ ImGui::InputTextMultiline("", cheat_buffer, IM_ARRAYSIZE(cheat_buffer));
+ ImGui::PopItemWidth();
+
+ ImGui::NextColumn();
+
+ if (ImGui::Button("Add Cheat Codes"))
+ {
+ std::string cheats = cheat_buffer;
+ std::istringstream ss(cheats);
+ std::string cheat;
+
+ while (getline(ss, cheat))
+ {
+ if ((cheat_list.size() < 50) && ((cheat.length() == 7) || (cheat.length() == 8) || (cheat.length() == 11)))
+ {
+ cheat_list.push_back(cheat);
+ emu_add_cheat(cheat.c_str());
+ cheat_buffer[0] = 0;
+ }
+ }
+ }
+
+ if (cheat_list.size() > 0)
+ {
+ if (ImGui::Button("Clear All"))
+ {
+ cheat_list.clear();
+ emu_clear_cheats();
+ }
+ }
+
+ ImGui::Columns(1);
+
+ std::list<std::string>::iterator it;
+
+ for (it = cheat_list.begin(); it != cheat_list.end(); it++)
+ {
+ if ((it->length() == 7) || (it->length() == 11))
+ ImGui::Text("Game Genie: %s", it->c_str());
+ else
+ ImGui::Text("GameShark: %s", it->c_str());
+ }
+
+ ImGui::EndMenu();
+ }
+
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Video"))
+ {
+ gui_in_use = true;
+
+ if (ImGui::MenuItem("Full Screen", "F11", &application_fullscreen))
+ {
+ application_trigger_fullscreen(application_fullscreen);
+ }
+
+ ImGui::MenuItem("Show Menu", "CTRL+M", &show_main_menu);
+
+ ImGui::Separator();
+
+ if (ImGui::BeginMenu("Scale"))
+ {
+ ImGui::PushItemWidth(100.0f);
+ ImGui::Combo("##scale", &config_video.scale, "Auto\0Zoom X1\0Zoom X2\0Zoom X3\0Zoom X4\0\0");
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Aspect Ratio"))
+ {
+ ImGui::PushItemWidth(130.0f);
+ ImGui::Combo("##ratio", &config_video.ratio, "Game Boy\0Standard (4:3)\0Wide (16:9)\0Fit Window\0\0");
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Vertical Sync", "", &config_video.sync))
+ {
+ SDL_GL_SetSwapInterval(config_video.sync ? 1 : 0);
+
+ if (config_video.sync)
+ {
+ config_audio.sync = true;
+ emu_audio_reset();
+ }
+ }
+
+ ImGui::MenuItem("Show FPS", "", &config_video.fps);
+
+ ImGui::Separator();
+
+ ImGui::MenuItem("Bilinear Filtering", "", &config_video.bilinear);
+
+ if (ImGui::MenuItem("Color Correction (GBC)", "", &config_video.color_correction))
+ {
+ emu_color_correction(config_video.color_correction);
+ }
+
+ if (ImGui::BeginMenu("Screen Ghosting"))
+ {
+ ImGui::MenuItem("Enable Screen Ghosting", "", &config_video.mix_frames);
+ ImGui::SliderFloat("##screen_ghosting", &config_video.mix_frames_intensity, 0.0f, 1.0f, "Intensity = %.2f");
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Dot Matrix"))
+ {
+ ImGui::MenuItem("Enable Dot Matrix", "", &config_video.matrix);
+ ImGui::SliderFloat("##dot_matrix", &config_video.matrix_intensity, 0.0f, 1.0f, "Intensity = %.2f");
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::BeginMenu("Palette"))
+ {
+ ImGui::PushItemWidth(130.0f);
+ if (ImGui::Combo("##palette", &config_video.palette, "Original\0Sharp\0Black & White\0Autumn\0Soft\0Slime\0Custom 1\0Custom 2\0Custom 3\0Custom 4\0Custom 5\0\0", 11))
+ {
+ update_palette();
+ }
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Custom Palettes"))
+ {
+
+ for (int i = 0; i < config_max_custom_palettes; i++)
+ {
+ char menu_label[256];
+ sprintf(menu_label, "Palette %i", i + 1);
+
+ if (ImGui::BeginMenu(menu_label))
+ {
+ if (ImGui::ColorEdit3("Color #1", (float*)&custom_palette[i][0], ImGuiColorEditFlags_NoInputs))
+ {
+ update_palette();
+ }
+ if (ImGui::ColorEdit3("Color #2", (float*)&custom_palette[i][1], ImGuiColorEditFlags_NoInputs))
+ {
+ update_palette();
+ }
+ if (ImGui::ColorEdit3("Color #3", (float*)&custom_palette[i][2], ImGuiColorEditFlags_NoInputs))
+ {
+ update_palette();
+ }
+ if (ImGui::ColorEdit3("Color #4", (float*)&custom_palette[i][3], ImGuiColorEditFlags_NoInputs))
+ {
+ update_palette();
+ }
+ ImGui::EndMenu();
+ }
+ }
+
+ ImGui::EndMenu();
+ }
+
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Input"))
+ {
+ gui_in_use = true;
+
+ if (ImGui::BeginMenu("Keyboard Configuration"))
+ {
+ keyboard_configuration_item("Left:", &config_input.key_left);
+ keyboard_configuration_item("Right:", &config_input.key_right);
+ keyboard_configuration_item("Up:", &config_input.key_up);
+ keyboard_configuration_item("Down:", &config_input.key_down);
+ keyboard_configuration_item("A:", &config_input.key_a);
+ keyboard_configuration_item("B:", &config_input.key_b);
+ keyboard_configuration_item("Start:", &config_input.key_start);
+ keyboard_configuration_item("Select:", &config_input.key_select);
+
+ popup_modal_keyboard();
+
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::BeginMenu("Gamepad"))
+ {
+ ImGui::MenuItem("Enable Gamepad", "", &config_input.gamepad);
+
+ if (ImGui::BeginMenu("Directional Controls"))
+ {
+ ImGui::PushItemWidth(150.0f);
+ ImGui::Combo("##directional", &config_input.gamepad_directional, "D-pad\0Left Analog Stick\0\0");
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Button Configuration"))
+ {
+ gamepad_configuration_item("A:", &config_input.gamepad_a);
+ gamepad_configuration_item("B:", &config_input.gamepad_b);
+ gamepad_configuration_item("START:", &config_input.gamepad_start);
+ gamepad_configuration_item("SELECT:", &config_input.gamepad_select);
+
+ popup_modal_gamepad();
+
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenu();
+ }
+
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Audio"))
+ {
+ gui_in_use = true;
+
+ if (ImGui::MenuItem("Enable Audio", "", &config_audio.enable))
+ {
+ emu_audio_volume(config_audio.enable ? 1.0f: 0.0f);
+ }
+
+ if (ImGui::MenuItem("Sync With Emulator", "", &config_audio.sync))
+ {
+ config_emulator.ffwd = false;
+
+ if (!config_audio.sync)
+ {
+ config_video.sync = false;
+ SDL_GL_SetSwapInterval(0);
+ }
+ }
+
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Debug"))
+ {
+ gui_in_use = true;
+
+ if (ImGui::MenuItem("Enable", "", &config_debug.debug))
+ {
+ if (config_debug.debug)
+ emu_debug_step();
+ else
+ emu_debug_continue();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Step Over", "CTRL + F10", (void*)0, config_debug.debug))
+ {
+ emu_debug_step();
+ }
+
+ if (ImGui::MenuItem("Step Frame", "CTRL + F6", (void*)0, config_debug.debug))
+ {
+ emu_debug_next_frame();
+ }
+
+ if (ImGui::MenuItem("Continue", "CTRL + F5", (void*)0, config_debug.debug))
+ {
+ emu_debug_continue();
+ }
+
+ if (ImGui::MenuItem("Run To Cursor", "CTRL + F8", (void*)0, config_debug.debug))
+ {
+ gui_debug_runtocursor();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Go Back", "CTRL + BACKSPACE", (void*)0, config_debug.debug))
+ {
+ gui_debug_go_back();
+ }
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Toggle Breakpoint", "CTRL + F9", (void*)0, config_debug.debug))
+ {
+ gui_debug_toggle_breakpoint();
+ }
+
+ if (ImGui::MenuItem("Clear All Processor Breakpoints", 0, (void*)0, config_debug.debug))
+ {
+ gui_debug_reset_breakpoints_cpu();
+ }
+
+ if (ImGui::MenuItem("Clear All Memory Breakpoints", 0, (void*)0, config_debug.debug))
+ {
+ gui_debug_reset_breakpoints_mem();
+ }
+
+ ImGui::MenuItem("Disable All Processor Breakpoints", 0, &emu_debug_disable_breakpoints_cpu, config_debug.debug);
+
+ ImGui::MenuItem("Disable All Memory Breakpoints", 0, &emu_debug_disable_breakpoints_mem, config_debug.debug);
+
+ ImGui::Separator();
+
+ if (ImGui::BeginMenu("Font Size", config_debug.debug))
+ {
+ ImGui::PushItemWidth(110.0f);
+ if (ImGui::Combo("##font", &config_debug.font_size, "Very Small\0Small\0Medium\0Large\0\0"))
+ {
+ gui_default_font = default_font[config_debug.font_size];
+ }
+ ImGui::PopItemWidth();
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+
+ ImGui::MenuItem("Show Game Boy Screen", "", &config_debug.show_gameboy, config_debug.debug);
+
+ ImGui::MenuItem("Show Disassembler", "", &config_debug.show_disassembler, config_debug.debug);
+
+ ImGui::MenuItem("Show Processor Status", "", &config_debug.show_processor, config_debug.debug);
+
+ ImGui::MenuItem("Show Memory Editor", "", &config_debug.show_memory, config_debug.debug);
+
+ ImGui::MenuItem("Show IO Map", "", &config_debug.show_iomap, config_debug.debug);
+
+ ImGui::MenuItem("Show VRAM Viewer", "", &config_debug.show_video, config_debug.debug);
+
+ ImGui::MenuItem("Show Sound Registers", "", &config_debug.show_audio, config_debug.debug);
+
+ ImGui::Separator();
+
+ if (ImGui::MenuItem("Load Symbols...", "", (void*)0, config_debug.debug))
+ {
+ open_symbols = true;
+ }
+
+ if (ImGui::MenuItem("Clear Symbols", "", (void*)0, config_debug.debug))
+ {
+ gui_debug_reset_symbols();
+ }
+
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("About"))
+ {
+ gui_in_use = true;
+
+ if (ImGui::MenuItem("About " GEARBOY_TITLE " " GEARBOY_VERSION " ..."))
+ {
+ open_about = true;
+ }
+ ImGui::EndMenu();
+ }
+
+ main_menu_height = (int)ImGui::GetWindowSize().y;
+
+ ImGui::EndMainMenuBar();
+ }
+
+ if (open_rom || shortcut_open_rom)
+ {
+ shortcut_open_rom = false;
+ ImGui::OpenPopup("Open ROM...");
+ }
+
+ if (open_ram)
+ ImGui::OpenPopup("Load RAM From...");
+
+ if (save_ram)
+ ImGui::OpenPopup("Save RAM As...");
+
+ if (open_state)
+ ImGui::OpenPopup("Load State From...");
+
+ if (save_state)
+ ImGui::OpenPopup("Save State As...");
+
+ if (choose_save_file_path)
+ ImGui::OpenPopup("Choose Save File Folder...");
+
+ if (choose_savestates_path)
+ ImGui::OpenPopup("Choose Savestate Folder...");
+
+ if (open_dmg_bootrom)
+ ImGui::OpenPopup("Load DMG Bootrom From...");
+
+ if (open_gbc_bootrom)
+ ImGui::OpenPopup("Load GBC Bootrom From...");
+
+ if (open_symbols)
+ ImGui::OpenPopup("Load Symbols File...");
+
+ if (open_about)
+ {
+ dialog_in_use = true;
+ ImGui::OpenPopup("About " GEARBOY_TITLE);
+ }
+
+ popup_modal_about();
+ file_dialog_open_rom();
+ file_dialog_load_ram();
+ file_dialog_save_ram();
+ file_dialog_load_state();
+ file_dialog_save_state();
+ file_dialog_choose_save_file_path();
+ file_dialog_choose_savestate_path();
+ file_dialog_load_dmg_bootrom();
+ file_dialog_load_gbc_bootrom();
+ file_dialog_load_symbols();
+
+ for (int i = 0; i < config_max_custom_palettes; i++)
+ for (int c = 0; c < 4; c++)
+ config_video.color[i][c] = color_float_to_int(custom_palette[i][c]);
+}
+
+static void main_window(void)
+{
+ int w = (int)ImGui::GetIO().DisplaySize.x;
+ int h = (int)ImGui::GetIO().DisplaySize.y - (show_main_menu ? main_menu_height : 0);
+
+ int selected_ratio = config_debug.debug ? 0 : config_video.ratio;
+ float ratio = (float)GAMEBOY_WIDTH / (float)GAMEBOY_HEIGHT;
+
+ switch (selected_ratio)
+ {
+ case 0:
+ ratio = (float)GAMEBOY_WIDTH / (float)GAMEBOY_HEIGHT;
+ break;
+ case 1:
+ ratio = 4.0f / 3.0f;
+ break;
+ case 2:
+ ratio = 16.0f / 9.0f;
+ break;
+ case 3:
+ ratio = (float)w / (float)h;
+ break;
+ default:
+ ratio = (float)GAMEBOY_WIDTH / (float)GAMEBOY_HEIGHT;
+ }
+
+ int w_corrected = (int)(selected_ratio == 3 ? w : GAMEBOY_HEIGHT * ratio);
+ int h_corrected = selected_ratio == 3 ? h : GAMEBOY_HEIGHT;
+
+ int factor = 0;
+
+ if (config_video.scale > 0)
+ {
+ factor = config_video.scale;
+ }
+ else if (config_debug.debug)
+ {
+ factor = 1;
+ }
+ else
+ {
+ int factor_w = w / w_corrected;
+ int factor_h = h / h_corrected;
+ factor = (factor_w < factor_h) ? factor_w : factor_h;
+ }
+
+ int main_window_width = w_corrected * factor;
+ int main_window_height = h_corrected * factor;
+
+ int window_x = (w - (w_corrected * factor)) / 2;
+ int window_y = ((h - (h_corrected * factor)) / 2) + (show_main_menu ? main_menu_height : 0);
+
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
+
+ ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar;
+
+ if (config_debug.debug)
+ {
+ flags |= ImGuiWindowFlags_AlwaysAutoResize;
+
+ ImGui::SetNextWindowPos(ImVec2(7, 32), ImGuiCond_FirstUseEver);
+
+ ImGui::Begin(emu_is_cgb() ? "Game Boy Color###debug_output" : "Game Boy###debug_output", &config_debug.show_gameboy, flags);
+ }
+ else
+ {
+ ImGui::SetNextWindowSize(ImVec2((float)main_window_width, (float)main_window_height));
+ ImGui::SetNextWindowPos(ImVec2((float)window_x, (float)window_y));
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
+
+ flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoNav;
+
+ ImGui::Begin(GEARBOY_TITLE, 0, flags);
+ }
+
+ ImGui::Image((void*)(intptr_t)renderer_emu_texture, ImVec2((float)main_window_width, (float)main_window_height));
+
+ if (config_video.fps)
+ show_fps();
+
+ if (config_emulator.show_info)
+ show_info();
+
+ ImGui::End();
+
+ ImGui::PopStyleVar();
+ ImGui::PopStyleVar();
+
+ if (!config_debug.debug)
+ {
+
+ ImGui::PopStyleVar();
+ }
+}
+
+static void file_dialog_open_rom(void)
+{
+ if(file_dialog.showFileDialog("Open ROM...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 400), "*.*,.gb,.gbc,.cgb,.sgb,.dmg,.rom,.zip", &dialog_in_use))
+ {
+ gui_load_rom(file_dialog.selected_path.c_str());
+ }
+}
+
+static void file_dialog_load_ram(void)
+{
+ if(file_dialog.showFileDialog("Load RAM From...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 310), ".sav,*.*", &dialog_in_use))
+ {
+ emu_load_ram(file_dialog.selected_path.c_str(), config_emulator.force_dmg, get_mbc(config_emulator.mbc), config_emulator.force_gba);
+ }
+}
+
+static void file_dialog_save_ram(void)
+{
+ if(file_dialog.showFileDialog("Save RAM As...", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE, ImVec2(700, 310), ".sav", &dialog_in_use))
+ {
+ std::string save_path = file_dialog.selected_path;
+
+ if (save_path.rfind(file_dialog.ext) != (save_path.size()-file_dialog.ext.size()))
+ {
+ save_path += file_dialog.ext;
+ }
+
+ emu_save_ram(save_path.c_str());
+ }
+}
+
+static void file_dialog_load_state(void)
+{
+ if(file_dialog.showFileDialog("Load State From...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 310), ".state,*.*", &dialog_in_use))
+ {
+ emu_load_state_file(file_dialog.selected_path.c_str());
+ }
+}
+
+static void file_dialog_save_state(void)
+{
+ if(file_dialog.showFileDialog("Save State As...", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE, ImVec2(700, 310), ".state", &dialog_in_use))
+ {
+ std::string state_path = file_dialog.selected_path;
+
+ if (state_path.rfind(file_dialog.ext) != (state_path.size()-file_dialog.ext.size()))
+ {
+ state_path += file_dialog.ext;
+ }
+
+ emu_save_state_file(state_path.c_str());
+ }
+}
+
+static void file_dialog_choose_save_file_path(void)
+{
+ if(file_dialog.showFileDialog("Choose Save File Folder...", imgui_addons::ImGuiFileBrowser::DialogMode::SELECT, ImVec2(700, 310), "*.*", &dialog_in_use))
+ {
+ strcpy(savefiles_path, file_dialog.selected_path.c_str());
+ config_emulator.savefiles_path.assign(file_dialog.selected_path);
+ }
+}
+
+static void file_dialog_choose_savestate_path(void)
+{
+ if(file_dialog.showFileDialog("Choose Savestate Folder...", imgui_addons::ImGuiFileBrowser::DialogMode::SELECT, ImVec2(700, 310), "*.*", &dialog_in_use))
+ {
+ strcpy(savestates_path, file_dialog.selected_path.c_str());
+ config_emulator.savestates_path.assign(file_dialog.selected_path);
+ }
+}
+
+static void file_dialog_load_dmg_bootrom(void)
+{
+ if(file_dialog.showFileDialog("Load DMG Bootrom From...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 310), ".bin,.gb,*.*", &dialog_in_use))
+ {
+ strcpy(dmg_bootrom_path, file_dialog.selected_path.c_str());
+ config_emulator.dmg_bootrom_path.assign(file_dialog.selected_path);
+
+ emu_load_bootrom_dmg(dmg_bootrom_path);
+ }
+}
+
+static void file_dialog_load_gbc_bootrom(void)
+{
+ if(file_dialog.showFileDialog("Load GBC Bootrom From...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 310), ".bin,.gbc,*.*", &dialog_in_use))
+ {
+ strcpy(gbc_bootrom_path, file_dialog.selected_path.c_str());
+ config_emulator.gbc_bootrom_path.assign(file_dialog.selected_path);
+
+ emu_load_bootrom_gbc(gbc_bootrom_path);
+ }
+}
+
+static void file_dialog_load_symbols(void)
+{
+ if(file_dialog.showFileDialog("Load Symbols File...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 400), ".sym,*.*", &dialog_in_use))
+ {
+ gui_debug_reset_symbols();
+ gui_debug_load_symbols_file(file_dialog.selected_path.c_str());
+ }
+}
+
+static void keyboard_configuration_item(const char* text, SDL_Scancode* key)
+{
+ ImGui::Text("%s", text);
+ ImGui::SameLine(90);
+
+ char button_label[256];
+ sprintf(button_label, "%s##%s", SDL_GetScancodeName(*key), text);
+
+ if (ImGui::Button(button_label, ImVec2(70,0)))
+ {
+ configured_key = key;
+ ImGui::OpenPopup("Keyboard Configuration");
+ }
+}
+
+static void gamepad_configuration_item(const char* text, int* button)
+{
+ ImGui::Text("%s", text);
+ ImGui::SameLine(70);
+
+ static const char* gamepad_names[16] = {"A", "B", "X" ,"Y", "BACK", "GUID", "START", "L3", "R3", "L1", "R1", "UP", "DOWN", "LEFT", "RIGHT", "15"};
+
+ char button_label[256];
+ sprintf(button_label, "%s##%s", gamepad_names[*button], text);
+
+ if (ImGui::Button(button_label, ImVec2(70,0)))
+ {
+ configured_button = button;
+ ImGui::OpenPopup("Gamepad Configuration");
+ }
+}
+
+static void popup_modal_keyboard(void)
+{
+ if (ImGui::BeginPopupModal("Keyboard Configuration", NULL, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::Text("Press any key...\n\n");
+ ImGui::Separator();
+
+ for (int i = 0; i < IM_ARRAYSIZE(ImGui::GetIO().KeysDown); i++)
+ {
+ if (ImGui::IsKeyPressed(i))
+ {
+ SDL_Scancode key = (SDL_Scancode)i;
+
+ if ((key != SDL_SCANCODE_LCTRL) && (key != SDL_SCANCODE_RCTRL) && (key != SDL_SCANCODE_CAPSLOCK))
+ {
+ *configured_key = key;
+ ImGui::CloseCurrentPopup();
+ break;
+ }
+ }
+ }
+
+ if (ImGui::Button("Cancel", ImVec2(120, 0)))
+ {
+ ImGui::CloseCurrentPopup();
+ }
+ ImGui::EndPopup();
+ }
+}
+
+static void popup_modal_gamepad(void)
+{
+ if (ImGui::BeginPopupModal("Gamepad Configuration", NULL, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::Text("Press any button in your gamepad...\n\n");
+ ImGui::Separator();
+
+ for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++)
+ {
+ if (SDL_GameControllerGetButton(application_gamepad, (SDL_GameControllerButton)i))
+ {
+ *configured_button = i;
+ ImGui::CloseCurrentPopup();
+ break;
+ }
+ }
+
+ if (ImGui::Button("Cancel", ImVec2(120, 0)))
+ {
+ ImGui::CloseCurrentPopup();
+ }
+ ImGui::EndPopup();
+ }
+}
+
+static void popup_modal_about(void)
+{
+ if (ImGui::BeginPopupModal("About " GEARBOY_TITLE, NULL, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::Text("%s %s", GEARBOY_TITLE, GEARBOY_VERSION);
+ ImGui::Text("Build: %s", EMULATOR_BUILD);
+
+ ImGui::Separator();
+
+ ImGui::Text("By Ignacio Sánchez (twitter.com/drhelius)");
+ ImGui::Text("%s is licensed under the GPL-3.0 License, see LICENSE for more information.", GEARBOY_TITLE);
+
+ ImGui::Separator();
+
+ if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
+ {
+ if (ImGui::BeginTabItem("Special thanks to"))
+ {
+ ImGui::BeginChild("backers", ImVec2(0, 100), false, ImGuiWindowFlags_AlwaysVerticalScrollbar);
+ ImGui::Text("%s", BACKERS_STR);
+ ImGui::EndChild();
+ ImGui::EndTabItem();
+ }
+ if (ImGui::BeginTabItem("LICENSE"))
+ {
+ ImGui::BeginChild("license", ImVec2(0, 100), false, ImGuiWindowFlags_AlwaysVerticalScrollbar);
+ ImGui::TextUnformatted(GPL_LICENSE_STR);
+ ImGui::EndChild();
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+
+ ImGui::Separator();
+
+ #ifdef _WIN64
+ ImGui::Text("Windows 64 bit build");
+ #elif defined(_WIN32)
+ ImGui::Text("Windows 32 bit build");
+ #endif
+ #ifdef __linux__
+ ImGui::Text("Linux build");
+ #endif
+ #ifdef __APPLE__
+ ImGui::Text("macOS build");
+ #endif
+ #ifdef _MSC_VER
+ ImGui::Text("Microsoft C++ %d.", _MSC_VER);
+ #endif
+ #ifdef __MINGW32__
+ ImGui::Text("MinGW 32 bit (%d.%d)", __MINGW32_MAJOR_VERSION, __MINGW32_MINOR_VERSION);
+ #endif
+ #ifdef __MINGW64__
+ ImGui::Text("MinGW 64 bit (%d.%d)", __MINGW64_VERSION_MAJOR, __MINGW64_VERSION_MINOR);
+ #endif
+ #if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER)
+ ImGui::Text("GCC %d.%d.%d", (int)__GNUC__, (int)__GNUC_MINOR__, (int)__GNUC_PATCHLEVEL__);
+ #endif
+ #ifdef __clang_version__
+ ImGui::Text("Clang %s", __clang_version__);
+ #endif
+
+ ImGui::Separator();
+
+ #ifdef DEBUG
+ ImGui::Text("define: DEBUG");
+ #endif
+ #ifdef DEBUG_GEARBOY
+ ImGui::Text("define: DEBUG_GEARBOY");
+ #endif
+ #ifdef __cplusplus
+ ImGui::Text("define: __cplusplus = %d", (int)__cplusplus);
+ #endif
+ #ifdef __STDC__
+ ImGui::Text("define: __STDC__ = %d", (int)__STDC__);
+ #endif
+ #ifdef __STDC_VERSION__
+ ImGui::Text("define: __STDC_VERSION__ = %d", (int)__STDC_VERSION__);
+ #endif
+
+ ImGui::Separator();
+
+ ImGui::Text("SDL %d.%d.%d (build)", application_sdl_build_version.major, application_sdl_build_version.minor, application_sdl_build_version.patch);
+ ImGui::Text("SDL %d.%d.%d (link) ", application_sdl_link_version.major, application_sdl_link_version.minor, application_sdl_link_version.patch);
+ ImGui::Text("OpenGL %s", renderer_opengl_version);
+ #ifndef __APPLE__
+ ImGui::Text("GLEW %s", renderer_glew_version);
+ #endif
+ ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
+
+ ImGui::Separator();
+
+ if (application_gamepad)
+ ImGui::Text("Gamepad detected");
+ else
+ ImGui::Text("No gamepad detected");
+
+ if (application_gamepad_mappings > 0)
+ ImGui::Text("%d gamepad mappings loaded", application_gamepad_mappings);
+ else
+ ImGui::Text("Gamepad database not found");
+
+ ImGui::Separator();
+
+ if (ImGui::Button("OK", ImVec2(120, 0)))
+ {
+ ImGui::CloseCurrentPopup();
+ dialog_in_use = false;
+ }
+ ImGui::SetItemDefaultFocus();
+
+ ImGui::EndPopup();
+ }
+}
+
+static GB_Color color_float_to_int(ImVec4 color)
+{
+ GB_Color ret;
+ ret.red = (u8)floor(color.x >= 1.0 ? 255.0 : color.x * 256.0);
+ ret.green = (u8)floor(color.y >= 1.0 ? 255.0 : color.y * 256.0);
+ ret.blue = (u8)floor(color.z >= 1.0 ? 255.0 : color.z * 256.0);
+ return ret;
+}
+
+static ImVec4 color_int_to_float(GB_Color color)
+{
+ ImVec4 ret;
+ ret.w = 0;
+ ret.x = (1.0f / 255.0f) * color.red;
+ ret.y = (1.0f / 255.0f) * color.green;
+ ret.z = (1.0f / 255.0f) * color.blue;
+ return ret;
+}
+
+static void update_palette(void)
+{
+ if (config_video.palette > 5)
+ {
+ int palette = config_video.palette - 6;
+ emu_dmg_palette(config_video.color[palette][0], config_video.color[palette][1], config_video.color[palette][2], config_video.color[palette][3]);
+ }
+ else
+ emu_dmg_predefined_palette(config_video.palette);
+}
+
+static void push_recent_rom(std::string path)
+{
+ int slot = 0;
+ for (slot = 0; slot < config_max_recent_roms; slot++)
+ {
+ if (config_emulator.recent_roms[slot].compare(path) == 0)
+ {
+ break;
+ }
+ }
+
+ slot = std::min(slot, config_max_recent_roms - 1);
+
+ for (int i = slot; i > 0; i--)
+ {
+ config_emulator.recent_roms[i] = config_emulator.recent_roms[i - 1];
+ }
+
+ config_emulator.recent_roms[0] = path;
+}
+
+static void menu_reset(void)
+{
+ emu_resume();
+ emu_reset(config_emulator.force_dmg, get_mbc(config_emulator.mbc), config_emulator.force_gba);
+
+ if (config_emulator.start_paused)
+ {
+ emu_pause();
+
+ for (int i=0; i < (GAMEBOY_WIDTH * GAMEBOY_HEIGHT); i++)
+ {
+ emu_frame_buffer[i].red = 0;
+ emu_frame_buffer[i].green = 0;
+ emu_frame_buffer[i].blue = 0;
+ }
+ }
+}
+
+static void menu_pause(void)
+{
+ if (emu_is_paused())
+ emu_resume();
+ else
+ emu_pause();
+}
+
+static void menu_ffwd(void)
+{
+ config_audio.sync = !config_emulator.ffwd;
+
+ if (config_emulator.ffwd)
+ SDL_GL_SetSwapInterval(0);
+ else
+ {
+ SDL_GL_SetSwapInterval(config_video.sync ? 1 : 0);
+ emu_audio_reset();
+ }
+}
+
+static void show_info(void)
+{
+ if (config_video.fps)
+ ImGui::SetCursorPosX(5.0f);
+ else
+ ImGui::SetCursorPos(ImVec2(5.0f, config_debug.debug ? 25.0f : 5.0f));
+
+ static char info[512];
+
+ emu_get_info(info);
+ ImGui::Text("%s", info);
+}
+
+static void show_fps(void)
+{
+ ImGui::SetCursorPos(ImVec2(5.0f, config_debug.debug ? 25.0f : 5.0f ));
+ ImGui::Text("Frame Rate: %.2f FPS\nFrame Time: %.2f ms", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate);
+}
+
+static Cartridge::CartridgeTypes get_mbc(int index)
+{
+ switch (index)
+ {
+ case 0:
+ return Cartridge::CartridgeNotSupported;
+ case 1:
+ return Cartridge::CartridgeNoMBC;
+ case 2:
+ return Cartridge::CartridgeMBC1;
+ case 3:
+ return Cartridge::CartridgeMBC2;
+ case 4:
+ return Cartridge::CartridgeMBC3;
+ case 5:
+ return Cartridge::CartridgeMBC5;
+ case 6:
+ return Cartridge::CartridgeMBC1Multi;
+ default:
+ return Cartridge::CartridgeNotSupported;
+ }
+}