gui.cpp (46455B)
1/* 2 * Gearboy - Nintendo Game Boy Emulator 3 * Copyright (C) 2012 Ignacio Sanchez 4 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * any later version. 9 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see http://www.gnu.org/licenses/ 17 * 18 */ 19 20#include "imgui/imgui.h" 21#include "imgui/imgui_memory_editor.h" 22#include "imgui/fonts/RobotoMedium.h" 23#include "FileBrowser/ImGuiFileBrowser.h" 24#include "config.h" 25#include "emu.h" 26#include "../../src/gearboy.h" 27#include "renderer.h" 28#include "application.h" 29#include "license.h" 30#include "backers.h" 31#include "gui_debug.h" 32 33#define GUI_IMPORT 34#include "gui.h" 35 36static imgui_addons::ImGuiFileBrowser file_dialog; 37static int main_menu_height; 38static bool dialog_in_use = false; 39static SDL_Scancode* configured_key; 40static int* configured_button; 41static ImVec4 custom_palette[config_max_custom_palettes][4]; 42static std::list<std::string> cheat_list; 43static bool shortcut_open_rom = false; 44static ImFont* default_font[4]; 45static char dmg_bootrom_path[4096] = ""; 46static char gbc_bootrom_path[4096] = ""; 47static char savefiles_path[4096] = ""; 48static char savestates_path[4096] = ""; 49static bool show_main_menu = true; 50 51static void main_menu(void); 52static void main_window(void); 53static void file_dialog_open_rom(void); 54static void file_dialog_load_ram(void); 55static void file_dialog_save_ram(void); 56static void file_dialog_load_state(void); 57static void file_dialog_save_state(void); 58static void file_dialog_choose_save_file_path(void); 59static void file_dialog_choose_savestate_path(void); 60static void file_dialog_load_dmg_bootrom(void); 61static void file_dialog_load_gbc_bootrom(void); 62static void file_dialog_load_symbols(void); 63static void keyboard_configuration_item(const char* text, SDL_Scancode* key); 64static void gamepad_configuration_item(const char* text, int* button); 65static void popup_modal_keyboard(void); 66static void popup_modal_gamepad(void); 67static void popup_modal_about(void); 68static GB_Color color_float_to_int(ImVec4 color); 69static ImVec4 color_int_to_float(GB_Color color); 70static void update_palette(void); 71static void push_recent_rom(std::string path); 72static void menu_reset(void); 73static void menu_pause(void); 74static void menu_ffwd(void); 75static void show_info(void); 76static void show_fps(void); 77static Cartridge::CartridgeTypes get_mbc(int index); 78 79void gui_init(void) 80{ 81 IMGUI_CHECKVERSION(); 82 ImGui::CreateContext(); 83 ImGui::StyleColorsDark(); 84 ImGuiIO& io = ImGui::GetIO(); 85 86 io.IniFilename = config_imgui_file_path; 87 88 io.FontGlobalScale /= application_display_scale; 89 90 gui_roboto_font = io.Fonts->AddFontFromMemoryCompressedTTF(RobotoMedium_compressed_data, RobotoMedium_compressed_size, 17.0f * application_display_scale, NULL, io.Fonts->GetGlyphRangesCyrillic()); 91 92 ImFontConfig font_cfg; 93 94 for (int i = 0; i < 4; i++) 95 { 96 font_cfg.SizePixels = (13.0f + (i * 3)) * application_display_scale; 97 default_font[i] = io.Fonts->AddFontDefault(&font_cfg); 98 } 99 100 gui_default_font = default_font[config_debug.font_size]; 101 102 update_palette(); 103 104 emu_audio_volume(config_audio.enable ? 1.0f: 0.0f); 105 emu_color_correction(config_video.color_correction); 106 107 strcpy(dmg_bootrom_path, config_emulator.dmg_bootrom_path.c_str()); 108 strcpy(gbc_bootrom_path, config_emulator.gbc_bootrom_path.c_str()); 109 strcpy(savefiles_path, config_emulator.savefiles_path.c_str()); 110 strcpy(savestates_path, config_emulator.savestates_path.c_str()); 111 112 if (strlen(dmg_bootrom_path) > 0) 113 emu_load_bootrom_dmg(dmg_bootrom_path); 114 if (strlen(gbc_bootrom_path) > 0) 115 emu_load_bootrom_gbc(gbc_bootrom_path); 116 117 emu_enable_bootrom_dmg(config_emulator.dmg_bootrom); 118 emu_enable_bootrom_gbc(config_emulator.gbc_bootrom); 119} 120 121void gui_destroy(void) 122{ 123 ImGui::DestroyContext(); 124} 125 126void gui_render(void) 127{ 128 ImGui::NewFrame(); 129 130 gui_in_use = dialog_in_use; 131 132 main_menu(); 133 134 if((!config_debug.debug && !emu_is_empty()) || (config_debug.debug && config_debug.show_gameboy)) 135 main_window(); 136 137 gui_debug_windows(); 138 139 ImGui::Render(); 140} 141 142void gui_shortcut(gui_ShortCutEvent event) 143{ 144 switch (event) 145 { 146 case gui_ShortcutOpenROM: 147 shortcut_open_rom = true; 148 break; 149 case gui_ShortcutReset: 150 menu_reset(); 151 break; 152 case gui_ShortcutPause: 153 menu_pause(); 154 break; 155 case gui_ShortcutFFWD: 156 config_emulator.ffwd = !config_emulator.ffwd; 157 menu_ffwd(); 158 break; 159 case gui_ShortcutSaveState: 160 emu_save_state_slot(config_emulator.save_slot + 1); 161 break; 162 case gui_ShortcutLoadState: 163 emu_load_state_slot(config_emulator.save_slot + 1); 164 break; 165 case gui_ShortcutDebugStep: 166 if (config_debug.debug) 167 emu_debug_step(); 168 break; 169 case gui_ShortcutDebugContinue: 170 if (config_debug.debug) 171 emu_debug_continue(); 172 break; 173 case gui_ShortcutDebugNextFrame: 174 if (config_debug.debug) 175 emu_debug_next_frame(); 176 break; 177 case gui_ShortcutDebugBreakpoint: 178 if (config_debug.debug) 179 gui_debug_toggle_breakpoint(); 180 break; 181 case gui_ShortcutDebugRuntocursor: 182 if (config_debug.debug) 183 gui_debug_runtocursor(); 184 break; 185 case gui_ShortcutDebugGoBack: 186 if (config_debug.debug) 187 gui_debug_go_back(); 188 break; 189 case gui_ShortcutShowMainMenu: 190 show_main_menu = !show_main_menu; 191 break; 192 default: 193 break; 194 } 195} 196 197void gui_load_rom(const char* path) 198{ 199 push_recent_rom(path); 200 emu_resume(); 201 emu_load_rom(path, config_emulator.force_dmg, get_mbc(config_emulator.mbc), config_emulator.force_gba); 202 cheat_list.clear(); 203 emu_clear_cheats(); 204 205 gui_debug_reset(); 206 207 std::string str(path); 208 str = str.substr(0, str.find_last_of(".")); 209 str += ".sym"; 210 gui_debug_load_symbols_file(str.c_str()); 211 212 if (config_emulator.start_paused) 213 { 214 emu_pause(); 215 216 for (int i=0; i < (GAMEBOY_WIDTH * GAMEBOY_HEIGHT); i++) 217 { 218 emu_frame_buffer[i].red = 0; 219 emu_frame_buffer[i].green = 0; 220 emu_frame_buffer[i].blue = 0; 221 } 222 } 223} 224 225static void main_menu(void) 226{ 227 bool open_rom = false; 228 bool open_ram = false; 229 bool save_ram = false; 230 bool open_state = false; 231 bool save_state = false; 232 bool open_about = false; 233 bool open_symbols = false; 234 bool choose_save_file_path = false; 235 bool choose_savestates_path = false; 236 bool open_dmg_bootrom = false; 237 bool open_gbc_bootrom = false; 238 239 for (int i = 0; i < config_max_custom_palettes; i++) 240 for (int c = 0; c < 4; c++) 241 custom_palette[i][c] = color_int_to_float(config_video.color[i][c]); 242 243 if (show_main_menu && ImGui::BeginMainMenuBar()) 244 { 245 if (ImGui::BeginMenu(GEARBOY_TITLE)) 246 { 247 gui_in_use = true; 248 249 if (ImGui::MenuItem("Open ROM...", "Ctrl+O")) 250 { 251 open_rom = true; 252 } 253 254 if (ImGui::BeginMenu("Open Recent")) 255 { 256 for (int i = 0; i < config_max_recent_roms; i++) 257 { 258 if (config_emulator.recent_roms[i].length() > 0) 259 { 260 if (ImGui::MenuItem(config_emulator.recent_roms[i].c_str())) 261 { 262 char rom_path[4096]; 263 strcpy(rom_path, config_emulator.recent_roms[i].c_str()); 264 gui_load_rom(rom_path); 265 } 266 } 267 } 268 269 ImGui::EndMenu(); 270 } 271 272 ImGui::Separator(); 273 274 if (ImGui::MenuItem("Reset", "Ctrl+R")) 275 { 276 menu_reset(); 277 } 278 279 if (ImGui::MenuItem("Pause", "Ctrl+P", &config_emulator.paused)) 280 { 281 menu_pause(); 282 } 283 284 ImGui::Separator(); 285 286 if (ImGui::MenuItem("Fast Forward", "Ctrl+F", &config_emulator.ffwd)) 287 { 288 menu_ffwd(); 289 } 290 291 if (ImGui::BeginMenu("Fast Forward Speed")) 292 { 293 ImGui::PushItemWidth(100.0f); 294 ImGui::Combo("##fwd", &config_emulator.ffwd_speed, "X 1.5\0X 2\0X 2.5\0X 3\0Unlimited\0\0"); 295 ImGui::PopItemWidth(); 296 ImGui::EndMenu(); 297 } 298 299 ImGui::Separator(); 300 301 if (ImGui::MenuItem("Save RAM As...")) 302 { 303 save_ram = true; 304 } 305 306 if (ImGui::MenuItem("Load RAM From...")) 307 { 308 open_ram = true; 309 } 310 311 ImGui::Separator(); 312 313 if (ImGui::MenuItem("Save State As...")) 314 { 315 save_state = true; 316 } 317 318 if (ImGui::MenuItem("Load State From...")) 319 { 320 open_state = true; 321 } 322 323 ImGui::Separator(); 324 325 if (ImGui::BeginMenu("Save State Slot")) 326 { 327 ImGui::PushItemWidth(100.0f); 328 ImGui::Combo("##slot", &config_emulator.save_slot, "Slot 1\0Slot 2\0Slot 3\0Slot 4\0Slot 5\0\0"); 329 ImGui::PopItemWidth(); 330 ImGui::EndMenu(); 331 } 332 333 if (ImGui::MenuItem("Save State", "Ctrl+S")) 334 { 335 emu_save_state_slot(config_emulator.save_slot + 1); 336 } 337 338 if (ImGui::MenuItem("Load State", "Ctrl+L")) 339 { 340 emu_load_state_slot(config_emulator.save_slot + 1); 341 } 342 343 ImGui::Separator(); 344 345 if (ImGui::MenuItem("Quit", "ESC")) 346 { 347 application_trigger_quit(); 348 } 349 350 ImGui::EndMenu(); 351 } 352 353 if (ImGui::BeginMenu("Emulator")) 354 { 355 gui_in_use = true; 356 357 if (ImGui::MenuItem("Force Game Boy (DMG)", "", &config_emulator.force_dmg)) 358 { 359 if (config_emulator.force_dmg) 360 config_emulator.force_gba = false; 361 } 362 363 if (ImGui::MenuItem("Force Game Boy Advance", "", &config_emulator.force_gba)) 364 { 365 if (config_emulator.force_gba) 366 config_emulator.force_dmg = false; 367 } 368 369 if (ImGui::BeginMenu("Memory Bank Controller")) 370 { 371 ImGui::PushItemWidth(140.0f); 372 ImGui::Combo("##mbc", &config_emulator.mbc, "Auto\0ROM Only\0MBC 1\0MBC 2\0MBC 3\0MBC 5\0MBC 1 Multicart\0\0"); 373 ImGui::PopItemWidth(); 374 ImGui::EndMenu(); 375 } 376 377 ImGui::Separator(); 378 379 if (ImGui::BeginMenu("DMG Bootrom")) 380 { 381 if (ImGui::MenuItem("Enable", "", &config_emulator.dmg_bootrom)) 382 { 383 emu_enable_bootrom_dmg(config_emulator.dmg_bootrom); 384 } 385 if (ImGui::IsItemHovered()) 386 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."); 387 if (ImGui::MenuItem("Load Bootrom...")) 388 { 389 open_dmg_bootrom = true; 390 } 391 ImGui::PushItemWidth(350); 392 if (ImGui::InputText("##dmg_bootrom_path", dmg_bootrom_path, IM_ARRAYSIZE(dmg_bootrom_path), ImGuiInputTextFlags_AutoSelectAll)) 393 { 394 config_emulator.dmg_bootrom_path.assign(dmg_bootrom_path); 395 emu_load_bootrom_dmg(dmg_bootrom_path); 396 } 397 ImGui::PopItemWidth(); 398 ImGui::EndMenu(); 399 } 400 401 if (ImGui::BeginMenu("GBC Bootrom")) 402 { 403 if (ImGui::MenuItem("Enable", "", &config_emulator.gbc_bootrom)) 404 { 405 emu_enable_bootrom_gbc(config_emulator.gbc_bootrom); 406 } 407 if (ImGui::IsItemHovered()) 408 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."); 409 if (ImGui::MenuItem("Load Bootrom...")) 410 { 411 open_gbc_bootrom = true; 412 } 413 ImGui::PushItemWidth(350); 414 if (ImGui::InputText("##gbc_bootrom_path", gbc_bootrom_path, IM_ARRAYSIZE(gbc_bootrom_path), ImGuiInputTextFlags_AutoSelectAll)) 415 { 416 config_emulator.gbc_bootrom_path.assign(gbc_bootrom_path); 417 emu_load_bootrom_gbc(gbc_bootrom_path); 418 } 419 ImGui::PopItemWidth(); 420 ImGui::EndMenu(); 421 } 422 423 ImGui::Separator(); 424 425 ImGui::MenuItem("Start Paused", "", &config_emulator.start_paused); 426 427 ImGui::Separator(); 428 429 if (ImGui::BeginMenu("Save File Location")) 430 { 431 ImGui::PushItemWidth(220.0f); 432 if (ImGui::Combo("##savefile_option", &config_emulator.savefiles_dir_option, "Save Files In Custom Folder\0Save Files In ROM Folder\0\0")) 433 { 434 emu_savefiles_dir_option = config_emulator.savefiles_dir_option; 435 } 436 437 if (config_emulator.savefiles_dir_option == 0) 438 { 439 if (ImGui::MenuItem("Choose Save File Folder...")) 440 { 441 choose_save_file_path = true; 442 } 443 444 ImGui::PushItemWidth(350); 445 if (ImGui::InputText("##savefile_path", savefiles_path, IM_ARRAYSIZE(savefiles_path), ImGuiInputTextFlags_AutoSelectAll)) 446 { 447 config_emulator.savefiles_path.assign(savefiles_path); 448 strcpy(emu_savefiles_path, savefiles_path); 449 } 450 ImGui::PopItemWidth(); 451 } 452 453 ImGui::EndMenu(); 454 } 455 456 if (ImGui::BeginMenu("Save State Location")) 457 { 458 ImGui::PushItemWidth(220.0f); 459 if (ImGui::Combo("##savestate_option", &config_emulator.savestates_dir_option, "Savestates In Custom Folder\0Savestates In ROM Folder\0\0")) 460 { 461 emu_savestates_dir_option = config_emulator.savestates_dir_option; 462 } 463 464 if (config_emulator.savestates_dir_option == 0) 465 { 466 if (ImGui::MenuItem("Choose Savestate Folder...")) 467 { 468 choose_savestates_path = true; 469 } 470 471 ImGui::PushItemWidth(350); 472 if (ImGui::InputText("##savestate_path", savestates_path, IM_ARRAYSIZE(savestates_path), ImGuiInputTextFlags_AutoSelectAll)) 473 { 474 config_emulator.savestates_path.assign(savestates_path); 475 strcpy(emu_savestates_path, savestates_path); 476 } 477 ImGui::PopItemWidth(); 478 } 479 480 ImGui::EndMenu(); 481 } 482 483 ImGui::Separator(); 484 485 ImGui::MenuItem("Show ROM info", "", &config_emulator.show_info); 486 487 ImGui::Separator(); 488 489 ImGui::SetNextWindowSizeConstraints({300.0f, 200.0f}, {300.0f, 500.0f}); 490 if (ImGui::BeginMenu("Cheats")) 491 { 492 ImGui::Text("Game Genie or GameShark codes\n(one code per line):"); 493 494 ImGui::Columns(2, "cheats", false); 495 496 static char cheat_buffer[20*50] = ""; 497 ImGui::PushItemWidth(150); 498 ImGui::InputTextMultiline("", cheat_buffer, IM_ARRAYSIZE(cheat_buffer)); 499 ImGui::PopItemWidth(); 500 501 ImGui::NextColumn(); 502 503 if (ImGui::Button("Add Cheat Codes")) 504 { 505 std::string cheats = cheat_buffer; 506 std::istringstream ss(cheats); 507 std::string cheat; 508 509 while (getline(ss, cheat)) 510 { 511 if ((cheat_list.size() < 50) && ((cheat.length() == 7) || (cheat.length() == 8) || (cheat.length() == 11))) 512 { 513 cheat_list.push_back(cheat); 514 emu_add_cheat(cheat.c_str()); 515 cheat_buffer[0] = 0; 516 } 517 } 518 } 519 520 if (cheat_list.size() > 0) 521 { 522 if (ImGui::Button("Clear All")) 523 { 524 cheat_list.clear(); 525 emu_clear_cheats(); 526 } 527 } 528 529 ImGui::Columns(1); 530 531 std::list<std::string>::iterator it; 532 533 for (it = cheat_list.begin(); it != cheat_list.end(); it++) 534 { 535 if ((it->length() == 7) || (it->length() == 11)) 536 ImGui::Text("Game Genie: %s", it->c_str()); 537 else 538 ImGui::Text("GameShark: %s", it->c_str()); 539 } 540 541 ImGui::EndMenu(); 542 } 543 544 ImGui::EndMenu(); 545 } 546 547 if (ImGui::BeginMenu("Video")) 548 { 549 gui_in_use = true; 550 551 if (ImGui::MenuItem("Full Screen", "F11", &application_fullscreen)) 552 { 553 application_trigger_fullscreen(application_fullscreen); 554 } 555 556 ImGui::MenuItem("Show Menu", "CTRL+M", &show_main_menu); 557 558 ImGui::Separator(); 559 560 if (ImGui::BeginMenu("Scale")) 561 { 562 ImGui::PushItemWidth(100.0f); 563 ImGui::Combo("##scale", &config_video.scale, "Auto\0Zoom X1\0Zoom X2\0Zoom X3\0Zoom X4\0\0"); 564 ImGui::PopItemWidth(); 565 ImGui::EndMenu(); 566 } 567 568 if (ImGui::BeginMenu("Aspect Ratio")) 569 { 570 ImGui::PushItemWidth(130.0f); 571 ImGui::Combo("##ratio", &config_video.ratio, "Game Boy\0Standard (4:3)\0Wide (16:9)\0Fit Window\0\0"); 572 ImGui::PopItemWidth(); 573 ImGui::EndMenu(); 574 } 575 576 ImGui::Separator(); 577 578 if (ImGui::MenuItem("Vertical Sync", "", &config_video.sync)) 579 { 580 SDL_GL_SetSwapInterval(config_video.sync ? 1 : 0); 581 582 if (config_video.sync) 583 { 584 config_audio.sync = true; 585 emu_audio_reset(); 586 } 587 } 588 589 ImGui::MenuItem("Show FPS", "", &config_video.fps); 590 591 ImGui::Separator(); 592 593 ImGui::MenuItem("Bilinear Filtering", "", &config_video.bilinear); 594 595 if (ImGui::MenuItem("Color Correction (GBC)", "", &config_video.color_correction)) 596 { 597 emu_color_correction(config_video.color_correction); 598 } 599 600 if (ImGui::BeginMenu("Screen Ghosting")) 601 { 602 ImGui::MenuItem("Enable Screen Ghosting", "", &config_video.mix_frames); 603 ImGui::SliderFloat("##screen_ghosting", &config_video.mix_frames_intensity, 0.0f, 1.0f, "Intensity = %.2f"); 604 ImGui::EndMenu(); 605 } 606 607 if (ImGui::BeginMenu("Dot Matrix")) 608 { 609 ImGui::MenuItem("Enable Dot Matrix", "", &config_video.matrix); 610 ImGui::SliderFloat("##dot_matrix", &config_video.matrix_intensity, 0.0f, 1.0f, "Intensity = %.2f"); 611 ImGui::EndMenu(); 612 } 613 614 ImGui::Separator(); 615 616 if (ImGui::BeginMenu("Palette")) 617 { 618 ImGui::PushItemWidth(130.0f); 619 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)) 620 { 621 update_palette(); 622 } 623 ImGui::PopItemWidth(); 624 ImGui::EndMenu(); 625 } 626 627 if (ImGui::BeginMenu("Custom Palettes")) 628 { 629 630 for (int i = 0; i < config_max_custom_palettes; i++) 631 { 632 char menu_label[256]; 633 sprintf(menu_label, "Palette %i", i + 1); 634 635 if (ImGui::BeginMenu(menu_label)) 636 { 637 if (ImGui::ColorEdit3("Color #1", (float*)&custom_palette[i][0], ImGuiColorEditFlags_NoInputs)) 638 { 639 update_palette(); 640 } 641 if (ImGui::ColorEdit3("Color #2", (float*)&custom_palette[i][1], ImGuiColorEditFlags_NoInputs)) 642 { 643 update_palette(); 644 } 645 if (ImGui::ColorEdit3("Color #3", (float*)&custom_palette[i][2], ImGuiColorEditFlags_NoInputs)) 646 { 647 update_palette(); 648 } 649 if (ImGui::ColorEdit3("Color #4", (float*)&custom_palette[i][3], ImGuiColorEditFlags_NoInputs)) 650 { 651 update_palette(); 652 } 653 ImGui::EndMenu(); 654 } 655 } 656 657 ImGui::EndMenu(); 658 } 659 660 ImGui::EndMenu(); 661 } 662 663 if (ImGui::BeginMenu("Input")) 664 { 665 gui_in_use = true; 666 667 if (ImGui::BeginMenu("Keyboard Configuration")) 668 { 669 keyboard_configuration_item("Left:", &config_input.key_left); 670 keyboard_configuration_item("Right:", &config_input.key_right); 671 keyboard_configuration_item("Up:", &config_input.key_up); 672 keyboard_configuration_item("Down:", &config_input.key_down); 673 keyboard_configuration_item("A:", &config_input.key_a); 674 keyboard_configuration_item("B:", &config_input.key_b); 675 keyboard_configuration_item("Start:", &config_input.key_start); 676 keyboard_configuration_item("Select:", &config_input.key_select); 677 678 popup_modal_keyboard(); 679 680 ImGui::EndMenu(); 681 } 682 683 ImGui::Separator(); 684 685 if (ImGui::BeginMenu("Gamepad")) 686 { 687 ImGui::MenuItem("Enable Gamepad", "", &config_input.gamepad); 688 689 if (ImGui::BeginMenu("Directional Controls")) 690 { 691 ImGui::PushItemWidth(150.0f); 692 ImGui::Combo("##directional", &config_input.gamepad_directional, "D-pad\0Left Analog Stick\0\0"); 693 ImGui::PopItemWidth(); 694 ImGui::EndMenu(); 695 } 696 697 if (ImGui::BeginMenu("Button Configuration")) 698 { 699 gamepad_configuration_item("A:", &config_input.gamepad_a); 700 gamepad_configuration_item("B:", &config_input.gamepad_b); 701 gamepad_configuration_item("START:", &config_input.gamepad_start); 702 gamepad_configuration_item("SELECT:", &config_input.gamepad_select); 703 704 popup_modal_gamepad(); 705 706 ImGui::EndMenu(); 707 } 708 ImGui::EndMenu(); 709 } 710 711 ImGui::EndMenu(); 712 } 713 714 if (ImGui::BeginMenu("Audio")) 715 { 716 gui_in_use = true; 717 718 if (ImGui::MenuItem("Enable Audio", "", &config_audio.enable)) 719 { 720 emu_audio_volume(config_audio.enable ? 1.0f: 0.0f); 721 } 722 723 if (ImGui::MenuItem("Sync With Emulator", "", &config_audio.sync)) 724 { 725 config_emulator.ffwd = false; 726 727 if (!config_audio.sync) 728 { 729 config_video.sync = false; 730 SDL_GL_SetSwapInterval(0); 731 } 732 } 733 734 ImGui::EndMenu(); 735 } 736 737 if (ImGui::BeginMenu("Debug")) 738 { 739 gui_in_use = true; 740 741 if (ImGui::MenuItem("Enable", "", &config_debug.debug)) 742 { 743 if (config_debug.debug) 744 emu_debug_step(); 745 else 746 emu_debug_continue(); 747 } 748 749 ImGui::Separator(); 750 751 if (ImGui::MenuItem("Step Over", "CTRL + F10", (void*)0, config_debug.debug)) 752 { 753 emu_debug_step(); 754 } 755 756 if (ImGui::MenuItem("Step Frame", "CTRL + F6", (void*)0, config_debug.debug)) 757 { 758 emu_debug_next_frame(); 759 } 760 761 if (ImGui::MenuItem("Continue", "CTRL + F5", (void*)0, config_debug.debug)) 762 { 763 emu_debug_continue(); 764 } 765 766 if (ImGui::MenuItem("Run To Cursor", "CTRL + F8", (void*)0, config_debug.debug)) 767 { 768 gui_debug_runtocursor(); 769 } 770 771 ImGui::Separator(); 772 773 if (ImGui::MenuItem("Go Back", "CTRL + BACKSPACE", (void*)0, config_debug.debug)) 774 { 775 gui_debug_go_back(); 776 } 777 778 ImGui::Separator(); 779 780 if (ImGui::MenuItem("Toggle Breakpoint", "CTRL + F9", (void*)0, config_debug.debug)) 781 { 782 gui_debug_toggle_breakpoint(); 783 } 784 785 if (ImGui::MenuItem("Clear All Processor Breakpoints", 0, (void*)0, config_debug.debug)) 786 { 787 gui_debug_reset_breakpoints_cpu(); 788 } 789 790 if (ImGui::MenuItem("Clear All Memory Breakpoints", 0, (void*)0, config_debug.debug)) 791 { 792 gui_debug_reset_breakpoints_mem(); 793 } 794 795 ImGui::MenuItem("Disable All Processor Breakpoints", 0, &emu_debug_disable_breakpoints_cpu, config_debug.debug); 796 797 ImGui::MenuItem("Disable All Memory Breakpoints", 0, &emu_debug_disable_breakpoints_mem, config_debug.debug); 798 799 ImGui::Separator(); 800 801 if (ImGui::BeginMenu("Font Size", config_debug.debug)) 802 { 803 ImGui::PushItemWidth(110.0f); 804 if (ImGui::Combo("##font", &config_debug.font_size, "Very Small\0Small\0Medium\0Large\0\0")) 805 { 806 gui_default_font = default_font[config_debug.font_size]; 807 } 808 ImGui::PopItemWidth(); 809 ImGui::EndMenu(); 810 } 811 812 ImGui::Separator(); 813 814 ImGui::MenuItem("Show Game Boy Screen", "", &config_debug.show_gameboy, config_debug.debug); 815 816 ImGui::MenuItem("Show Disassembler", "", &config_debug.show_disassembler, config_debug.debug); 817 818 ImGui::MenuItem("Show Processor Status", "", &config_debug.show_processor, config_debug.debug); 819 820 ImGui::MenuItem("Show Memory Editor", "", &config_debug.show_memory, config_debug.debug); 821 822 ImGui::MenuItem("Show IO Map", "", &config_debug.show_iomap, config_debug.debug); 823 824 ImGui::MenuItem("Show VRAM Viewer", "", &config_debug.show_video, config_debug.debug); 825 826 ImGui::MenuItem("Show Sound Registers", "", &config_debug.show_audio, config_debug.debug); 827 828 ImGui::Separator(); 829 830 if (ImGui::MenuItem("Load Symbols...", "", (void*)0, config_debug.debug)) 831 { 832 open_symbols = true; 833 } 834 835 if (ImGui::MenuItem("Clear Symbols", "", (void*)0, config_debug.debug)) 836 { 837 gui_debug_reset_symbols(); 838 } 839 840 ImGui::EndMenu(); 841 } 842 843 if (ImGui::BeginMenu("About")) 844 { 845 gui_in_use = true; 846 847 if (ImGui::MenuItem("About " GEARBOY_TITLE " " GEARBOY_VERSION " ...")) 848 { 849 open_about = true; 850 } 851 ImGui::EndMenu(); 852 } 853 854 main_menu_height = (int)ImGui::GetWindowSize().y; 855 856 ImGui::EndMainMenuBar(); 857 } 858 859 if (open_rom || shortcut_open_rom) 860 { 861 shortcut_open_rom = false; 862 ImGui::OpenPopup("Open ROM..."); 863 } 864 865 if (open_ram) 866 ImGui::OpenPopup("Load RAM From..."); 867 868 if (save_ram) 869 ImGui::OpenPopup("Save RAM As..."); 870 871 if (open_state) 872 ImGui::OpenPopup("Load State From..."); 873 874 if (save_state) 875 ImGui::OpenPopup("Save State As..."); 876 877 if (choose_save_file_path) 878 ImGui::OpenPopup("Choose Save File Folder..."); 879 880 if (choose_savestates_path) 881 ImGui::OpenPopup("Choose Savestate Folder..."); 882 883 if (open_dmg_bootrom) 884 ImGui::OpenPopup("Load DMG Bootrom From..."); 885 886 if (open_gbc_bootrom) 887 ImGui::OpenPopup("Load GBC Bootrom From..."); 888 889 if (open_symbols) 890 ImGui::OpenPopup("Load Symbols File..."); 891 892 if (open_about) 893 { 894 dialog_in_use = true; 895 ImGui::OpenPopup("About " GEARBOY_TITLE); 896 } 897 898 popup_modal_about(); 899 file_dialog_open_rom(); 900 file_dialog_load_ram(); 901 file_dialog_save_ram(); 902 file_dialog_load_state(); 903 file_dialog_save_state(); 904 file_dialog_choose_save_file_path(); 905 file_dialog_choose_savestate_path(); 906 file_dialog_load_dmg_bootrom(); 907 file_dialog_load_gbc_bootrom(); 908 file_dialog_load_symbols(); 909 910 for (int i = 0; i < config_max_custom_palettes; i++) 911 for (int c = 0; c < 4; c++) 912 config_video.color[i][c] = color_float_to_int(custom_palette[i][c]); 913} 914 915static void main_window(void) 916{ 917 int w = (int)ImGui::GetIO().DisplaySize.x; 918 int h = (int)ImGui::GetIO().DisplaySize.y - (show_main_menu ? main_menu_height : 0); 919 920 int selected_ratio = config_debug.debug ? 0 : config_video.ratio; 921 float ratio = (float)GAMEBOY_WIDTH / (float)GAMEBOY_HEIGHT; 922 923 switch (selected_ratio) 924 { 925 case 0: 926 ratio = (float)GAMEBOY_WIDTH / (float)GAMEBOY_HEIGHT; 927 break; 928 case 1: 929 ratio = 4.0f / 3.0f; 930 break; 931 case 2: 932 ratio = 16.0f / 9.0f; 933 break; 934 case 3: 935 ratio = (float)w / (float)h; 936 break; 937 default: 938 ratio = (float)GAMEBOY_WIDTH / (float)GAMEBOY_HEIGHT; 939 } 940 941 int w_corrected = (int)(selected_ratio == 3 ? w : GAMEBOY_HEIGHT * ratio); 942 int h_corrected = selected_ratio == 3 ? h : GAMEBOY_HEIGHT; 943 944 int factor = 0; 945 946 if (config_video.scale > 0) 947 { 948 factor = config_video.scale; 949 } 950 else if (config_debug.debug) 951 { 952 factor = 1; 953 } 954 else 955 { 956 int factor_w = w / w_corrected; 957 int factor_h = h / h_corrected; 958 factor = (factor_w < factor_h) ? factor_w : factor_h; 959 } 960 961 int main_window_width = w_corrected * factor; 962 int main_window_height = h_corrected * factor; 963 964 int window_x = (w - (w_corrected * factor)) / 2; 965 int window_y = ((h - (h_corrected * factor)) / 2) + (show_main_menu ? main_menu_height : 0); 966 967 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); 968 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); 969 970 ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar; 971 972 if (config_debug.debug) 973 { 974 flags |= ImGuiWindowFlags_AlwaysAutoResize; 975 976 ImGui::SetNextWindowPos(ImVec2(7, 32), ImGuiCond_FirstUseEver); 977 978 ImGui::Begin(emu_is_cgb() ? "Game Boy Color###debug_output" : "Game Boy###debug_output", &config_debug.show_gameboy, flags); 979 } 980 else 981 { 982 ImGui::SetNextWindowSize(ImVec2((float)main_window_width, (float)main_window_height)); 983 ImGui::SetNextWindowPos(ImVec2((float)window_x, (float)window_y)); 984 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); 985 986 flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoNav; 987 988 ImGui::Begin(GEARBOY_TITLE, 0, flags); 989 } 990 991 ImGui::Image((void*)(intptr_t)renderer_emu_texture, ImVec2((float)main_window_width, (float)main_window_height)); 992 993 if (config_video.fps) 994 show_fps(); 995 996 if (config_emulator.show_info) 997 show_info(); 998 999 ImGui::End(); 1000 1001 ImGui::PopStyleVar(); 1002 ImGui::PopStyleVar(); 1003 1004 if (!config_debug.debug) 1005 { 1006 1007 ImGui::PopStyleVar(); 1008 } 1009} 1010 1011static void file_dialog_open_rom(void) 1012{ 1013 if(file_dialog.showFileDialog("Open ROM...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 400), "*.*,.gb,.gbc,.cgb,.sgb,.dmg,.rom,.zip", &dialog_in_use)) 1014 { 1015 gui_load_rom(file_dialog.selected_path.c_str()); 1016 } 1017} 1018 1019static void file_dialog_load_ram(void) 1020{ 1021 if(file_dialog.showFileDialog("Load RAM From...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 310), ".sav,*.*", &dialog_in_use)) 1022 { 1023 emu_load_ram(file_dialog.selected_path.c_str(), config_emulator.force_dmg, get_mbc(config_emulator.mbc), config_emulator.force_gba); 1024 } 1025} 1026 1027static void file_dialog_save_ram(void) 1028{ 1029 if(file_dialog.showFileDialog("Save RAM As...", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE, ImVec2(700, 310), ".sav", &dialog_in_use)) 1030 { 1031 std::string save_path = file_dialog.selected_path; 1032 1033 if (save_path.rfind(file_dialog.ext) != (save_path.size()-file_dialog.ext.size())) 1034 { 1035 save_path += file_dialog.ext; 1036 } 1037 1038 emu_save_ram(save_path.c_str()); 1039 } 1040} 1041 1042static void file_dialog_load_state(void) 1043{ 1044 if(file_dialog.showFileDialog("Load State From...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 310), ".state,*.*", &dialog_in_use)) 1045 { 1046 emu_load_state_file(file_dialog.selected_path.c_str()); 1047 } 1048} 1049 1050static void file_dialog_save_state(void) 1051{ 1052 if(file_dialog.showFileDialog("Save State As...", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE, ImVec2(700, 310), ".state", &dialog_in_use)) 1053 { 1054 std::string state_path = file_dialog.selected_path; 1055 1056 if (state_path.rfind(file_dialog.ext) != (state_path.size()-file_dialog.ext.size())) 1057 { 1058 state_path += file_dialog.ext; 1059 } 1060 1061 emu_save_state_file(state_path.c_str()); 1062 } 1063} 1064 1065static void file_dialog_choose_save_file_path(void) 1066{ 1067 if(file_dialog.showFileDialog("Choose Save File Folder...", imgui_addons::ImGuiFileBrowser::DialogMode::SELECT, ImVec2(700, 310), "*.*", &dialog_in_use)) 1068 { 1069 strcpy(savefiles_path, file_dialog.selected_path.c_str()); 1070 config_emulator.savefiles_path.assign(file_dialog.selected_path); 1071 } 1072} 1073 1074static void file_dialog_choose_savestate_path(void) 1075{ 1076 if(file_dialog.showFileDialog("Choose Savestate Folder...", imgui_addons::ImGuiFileBrowser::DialogMode::SELECT, ImVec2(700, 310), "*.*", &dialog_in_use)) 1077 { 1078 strcpy(savestates_path, file_dialog.selected_path.c_str()); 1079 config_emulator.savestates_path.assign(file_dialog.selected_path); 1080 } 1081} 1082 1083static void file_dialog_load_dmg_bootrom(void) 1084{ 1085 if(file_dialog.showFileDialog("Load DMG Bootrom From...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 310), ".bin,.gb,*.*", &dialog_in_use)) 1086 { 1087 strcpy(dmg_bootrom_path, file_dialog.selected_path.c_str()); 1088 config_emulator.dmg_bootrom_path.assign(file_dialog.selected_path); 1089 1090 emu_load_bootrom_dmg(dmg_bootrom_path); 1091 } 1092} 1093 1094static void file_dialog_load_gbc_bootrom(void) 1095{ 1096 if(file_dialog.showFileDialog("Load GBC Bootrom From...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 310), ".bin,.gbc,*.*", &dialog_in_use)) 1097 { 1098 strcpy(gbc_bootrom_path, file_dialog.selected_path.c_str()); 1099 config_emulator.gbc_bootrom_path.assign(file_dialog.selected_path); 1100 1101 emu_load_bootrom_gbc(gbc_bootrom_path); 1102 } 1103} 1104 1105static void file_dialog_load_symbols(void) 1106{ 1107 if(file_dialog.showFileDialog("Load Symbols File...", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 400), ".sym,*.*", &dialog_in_use)) 1108 { 1109 gui_debug_reset_symbols(); 1110 gui_debug_load_symbols_file(file_dialog.selected_path.c_str()); 1111 } 1112} 1113 1114static void keyboard_configuration_item(const char* text, SDL_Scancode* key) 1115{ 1116 ImGui::Text("%s", text); 1117 ImGui::SameLine(90); 1118 1119 char button_label[256]; 1120 sprintf(button_label, "%s##%s", SDL_GetScancodeName(*key), text); 1121 1122 if (ImGui::Button(button_label, ImVec2(70,0))) 1123 { 1124 configured_key = key; 1125 ImGui::OpenPopup("Keyboard Configuration"); 1126 } 1127} 1128 1129static void gamepad_configuration_item(const char* text, int* button) 1130{ 1131 ImGui::Text("%s", text); 1132 ImGui::SameLine(70); 1133 1134 static const char* gamepad_names[16] = {"A", "B", "X" ,"Y", "BACK", "GUID", "START", "L3", "R3", "L1", "R1", "UP", "DOWN", "LEFT", "RIGHT", "15"}; 1135 1136 char button_label[256]; 1137 sprintf(button_label, "%s##%s", gamepad_names[*button], text); 1138 1139 if (ImGui::Button(button_label, ImVec2(70,0))) 1140 { 1141 configured_button = button; 1142 ImGui::OpenPopup("Gamepad Configuration"); 1143 } 1144} 1145 1146static void popup_modal_keyboard(void) 1147{ 1148 if (ImGui::BeginPopupModal("Keyboard Configuration", NULL, ImGuiWindowFlags_AlwaysAutoResize)) 1149 { 1150 ImGui::Text("Press any key...\n\n"); 1151 ImGui::Separator(); 1152 1153 for (int i = 0; i < IM_ARRAYSIZE(ImGui::GetIO().KeysDown); i++) 1154 { 1155 if (ImGui::IsKeyPressed(i)) 1156 { 1157 SDL_Scancode key = (SDL_Scancode)i; 1158 1159 if ((key != SDL_SCANCODE_LCTRL) && (key != SDL_SCANCODE_RCTRL) && (key != SDL_SCANCODE_CAPSLOCK)) 1160 { 1161 *configured_key = key; 1162 ImGui::CloseCurrentPopup(); 1163 break; 1164 } 1165 } 1166 } 1167 1168 if (ImGui::Button("Cancel", ImVec2(120, 0))) 1169 { 1170 ImGui::CloseCurrentPopup(); 1171 } 1172 ImGui::EndPopup(); 1173 } 1174} 1175 1176static void popup_modal_gamepad(void) 1177{ 1178 if (ImGui::BeginPopupModal("Gamepad Configuration", NULL, ImGuiWindowFlags_AlwaysAutoResize)) 1179 { 1180 ImGui::Text("Press any button in your gamepad...\n\n"); 1181 ImGui::Separator(); 1182 1183 for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++) 1184 { 1185 if (SDL_GameControllerGetButton(application_gamepad, (SDL_GameControllerButton)i)) 1186 { 1187 *configured_button = i; 1188 ImGui::CloseCurrentPopup(); 1189 break; 1190 } 1191 } 1192 1193 if (ImGui::Button("Cancel", ImVec2(120, 0))) 1194 { 1195 ImGui::CloseCurrentPopup(); 1196 } 1197 ImGui::EndPopup(); 1198 } 1199} 1200 1201static void popup_modal_about(void) 1202{ 1203 if (ImGui::BeginPopupModal("About " GEARBOY_TITLE, NULL, ImGuiWindowFlags_AlwaysAutoResize)) 1204 { 1205 ImGui::Text("%s %s", GEARBOY_TITLE, GEARBOY_VERSION); 1206 ImGui::Text("Build: %s", EMULATOR_BUILD); 1207 1208 ImGui::Separator(); 1209 1210 ImGui::Text("By Ignacio Sánchez (twitter.com/drhelius)"); 1211 ImGui::Text("%s is licensed under the GPL-3.0 License, see LICENSE for more information.", GEARBOY_TITLE); 1212 1213 ImGui::Separator(); 1214 1215 if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None)) 1216 { 1217 if (ImGui::BeginTabItem("Special thanks to")) 1218 { 1219 ImGui::BeginChild("backers", ImVec2(0, 100), false, ImGuiWindowFlags_AlwaysVerticalScrollbar); 1220 ImGui::Text("%s", BACKERS_STR); 1221 ImGui::EndChild(); 1222 ImGui::EndTabItem(); 1223 } 1224 if (ImGui::BeginTabItem("LICENSE")) 1225 { 1226 ImGui::BeginChild("license", ImVec2(0, 100), false, ImGuiWindowFlags_AlwaysVerticalScrollbar); 1227 ImGui::TextUnformatted(GPL_LICENSE_STR); 1228 ImGui::EndChild(); 1229 ImGui::EndTabItem(); 1230 } 1231 ImGui::EndTabBar(); 1232 } 1233 1234 ImGui::Separator(); 1235 1236 #ifdef _WIN64 1237 ImGui::Text("Windows 64 bit build"); 1238 #elif defined(_WIN32) 1239 ImGui::Text("Windows 32 bit build"); 1240 #endif 1241 #ifdef __linux__ 1242 ImGui::Text("Linux build"); 1243 #endif 1244 #ifdef __APPLE__ 1245 ImGui::Text("macOS build"); 1246 #endif 1247 #ifdef _MSC_VER 1248 ImGui::Text("Microsoft C++ %d.", _MSC_VER); 1249 #endif 1250 #ifdef __MINGW32__ 1251 ImGui::Text("MinGW 32 bit (%d.%d)", __MINGW32_MAJOR_VERSION, __MINGW32_MINOR_VERSION); 1252 #endif 1253 #ifdef __MINGW64__ 1254 ImGui::Text("MinGW 64 bit (%d.%d)", __MINGW64_VERSION_MAJOR, __MINGW64_VERSION_MINOR); 1255 #endif 1256 #if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) 1257 ImGui::Text("GCC %d.%d.%d", (int)__GNUC__, (int)__GNUC_MINOR__, (int)__GNUC_PATCHLEVEL__); 1258 #endif 1259 #ifdef __clang_version__ 1260 ImGui::Text("Clang %s", __clang_version__); 1261 #endif 1262 1263 ImGui::Separator(); 1264 1265 #ifdef DEBUG 1266 ImGui::Text("define: DEBUG"); 1267 #endif 1268 #ifdef DEBUG_GEARBOY 1269 ImGui::Text("define: DEBUG_GEARBOY"); 1270 #endif 1271 #ifdef __cplusplus 1272 ImGui::Text("define: __cplusplus = %d", (int)__cplusplus); 1273 #endif 1274 #ifdef __STDC__ 1275 ImGui::Text("define: __STDC__ = %d", (int)__STDC__); 1276 #endif 1277 #ifdef __STDC_VERSION__ 1278 ImGui::Text("define: __STDC_VERSION__ = %d", (int)__STDC_VERSION__); 1279 #endif 1280 1281 ImGui::Separator(); 1282 1283 ImGui::Text("SDL %d.%d.%d (build)", application_sdl_build_version.major, application_sdl_build_version.minor, application_sdl_build_version.patch); 1284 ImGui::Text("SDL %d.%d.%d (link) ", application_sdl_link_version.major, application_sdl_link_version.minor, application_sdl_link_version.patch); 1285 ImGui::Text("OpenGL %s", renderer_opengl_version); 1286 #ifndef __APPLE__ 1287 ImGui::Text("GLEW %s", renderer_glew_version); 1288 #endif 1289 ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM); 1290 1291 ImGui::Separator(); 1292 1293 if (application_gamepad) 1294 ImGui::Text("Gamepad detected"); 1295 else 1296 ImGui::Text("No gamepad detected"); 1297 1298 if (application_gamepad_mappings > 0) 1299 ImGui::Text("%d gamepad mappings loaded", application_gamepad_mappings); 1300 else 1301 ImGui::Text("Gamepad database not found"); 1302 1303 ImGui::Separator(); 1304 1305 if (ImGui::Button("OK", ImVec2(120, 0))) 1306 { 1307 ImGui::CloseCurrentPopup(); 1308 dialog_in_use = false; 1309 } 1310 ImGui::SetItemDefaultFocus(); 1311 1312 ImGui::EndPopup(); 1313 } 1314} 1315 1316static GB_Color color_float_to_int(ImVec4 color) 1317{ 1318 GB_Color ret; 1319 ret.red = (u8)floor(color.x >= 1.0 ? 255.0 : color.x * 256.0); 1320 ret.green = (u8)floor(color.y >= 1.0 ? 255.0 : color.y * 256.0); 1321 ret.blue = (u8)floor(color.z >= 1.0 ? 255.0 : color.z * 256.0); 1322 return ret; 1323} 1324 1325static ImVec4 color_int_to_float(GB_Color color) 1326{ 1327 ImVec4 ret; 1328 ret.w = 0; 1329 ret.x = (1.0f / 255.0f) * color.red; 1330 ret.y = (1.0f / 255.0f) * color.green; 1331 ret.z = (1.0f / 255.0f) * color.blue; 1332 return ret; 1333} 1334 1335static void update_palette(void) 1336{ 1337 if (config_video.palette > 5) 1338 { 1339 int palette = config_video.palette - 6; 1340 emu_dmg_palette(config_video.color[palette][0], config_video.color[palette][1], config_video.color[palette][2], config_video.color[palette][3]); 1341 } 1342 else 1343 emu_dmg_predefined_palette(config_video.palette); 1344} 1345 1346static void push_recent_rom(std::string path) 1347{ 1348 int slot = 0; 1349 for (slot = 0; slot < config_max_recent_roms; slot++) 1350 { 1351 if (config_emulator.recent_roms[slot].compare(path) == 0) 1352 { 1353 break; 1354 } 1355 } 1356 1357 slot = std::min(slot, config_max_recent_roms - 1); 1358 1359 for (int i = slot; i > 0; i--) 1360 { 1361 config_emulator.recent_roms[i] = config_emulator.recent_roms[i - 1]; 1362 } 1363 1364 config_emulator.recent_roms[0] = path; 1365} 1366 1367static void menu_reset(void) 1368{ 1369 emu_resume(); 1370 emu_reset(config_emulator.force_dmg, get_mbc(config_emulator.mbc), config_emulator.force_gba); 1371 1372 if (config_emulator.start_paused) 1373 { 1374 emu_pause(); 1375 1376 for (int i=0; i < (GAMEBOY_WIDTH * GAMEBOY_HEIGHT); i++) 1377 { 1378 emu_frame_buffer[i].red = 0; 1379 emu_frame_buffer[i].green = 0; 1380 emu_frame_buffer[i].blue = 0; 1381 } 1382 } 1383} 1384 1385static void menu_pause(void) 1386{ 1387 if (emu_is_paused()) 1388 emu_resume(); 1389 else 1390 emu_pause(); 1391} 1392 1393static void menu_ffwd(void) 1394{ 1395 config_audio.sync = !config_emulator.ffwd; 1396 1397 if (config_emulator.ffwd) 1398 SDL_GL_SetSwapInterval(0); 1399 else 1400 { 1401 SDL_GL_SetSwapInterval(config_video.sync ? 1 : 0); 1402 emu_audio_reset(); 1403 } 1404} 1405 1406static void show_info(void) 1407{ 1408 if (config_video.fps) 1409 ImGui::SetCursorPosX(5.0f); 1410 else 1411 ImGui::SetCursorPos(ImVec2(5.0f, config_debug.debug ? 25.0f : 5.0f)); 1412 1413 static char info[512]; 1414 1415 emu_get_info(info); 1416 ImGui::Text("%s", info); 1417} 1418 1419static void show_fps(void) 1420{ 1421 ImGui::SetCursorPos(ImVec2(5.0f, config_debug.debug ? 25.0f : 5.0f )); 1422 ImGui::Text("Frame Rate: %.2f FPS\nFrame Time: %.2f ms", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate); 1423} 1424 1425static Cartridge::CartridgeTypes get_mbc(int index) 1426{ 1427 switch (index) 1428 { 1429 case 0: 1430 return Cartridge::CartridgeNotSupported; 1431 case 1: 1432 return Cartridge::CartridgeNoMBC; 1433 case 2: 1434 return Cartridge::CartridgeMBC1; 1435 case 3: 1436 return Cartridge::CartridgeMBC2; 1437 case 4: 1438 return Cartridge::CartridgeMBC3; 1439 case 5: 1440 return Cartridge::CartridgeMBC5; 1441 case 6: 1442 return Cartridge::CartridgeMBC1Multi; 1443 default: 1444 return Cartridge::CartridgeNotSupported; 1445 } 1446}