// Copyright 2013 Dolphin Emulator Project // Licensed under GPLv2 // Refer to the license.txt file included. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "AudioCommon/AudioCommon.h" #include "Common/CommonPaths.h" #include "Common/CommonTypes.h" #include "Common/FileSearch.h" #include "Common/SysConf.h" #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/HotkeyManager.h" #include "Core/Movie.h" #include "Core/NetPlayProto.h" #include "Core/HW/EXI.h" #include "Core/HW/GCMemcard.h" #include "Core/HW/SI.h" #include "Core/HW/DSPHLE/DSPHLE.h" #include "Core/HW/DSPLLE/DSPLLE.h" #include "Core/IPC_HLE/WII_IPC_HLE.h" #include "Core/PowerPC/PowerPC.h" #include "DiscIO/NANDContentLoader.h" #include "DolphinWX/ConfigMain.h" #include "DolphinWX/Frame.h" #include "DolphinWX/Globals.h" #include "DolphinWX/HotkeyDlg.h" #include "DolphinWX/InputConfigDiag.h" #include "DolphinWX/Main.h" #include "DolphinWX/WxUtils.h" #include "DolphinWX/Debugger/CodeWindow.h" #include "InputCommon/InputConfig.h" #include "VideoCommon/VideoBackendBase.h" #define TEXT_BOX(page, text) new wxStaticText(page, wxID_ANY, text) struct CPUCore { int CPUid; const char *name; }; const CPUCore CPUCores[] = { {0, wxTRANSLATE("Interpreter (VERY slow)")}, #ifdef _M_X86_64 {1, wxTRANSLATE("JIT Recompiler (recommended)")}, {2, wxTRANSLATE("JITIL Recompiler (slower, experimental)")}, #elif defined(_M_ARM_32) {3, wxTRANSLATE("Arm JIT (experimental)")}, #elif defined(_M_ARM_64) {4, wxTRANSLATE("Arm64 JIT (experimental)")}, #endif }; // keep these in sync with CConfigMain::InitializeGUILists static const wxLanguage langIds[] = { wxLANGUAGE_DEFAULT, wxLANGUAGE_CATALAN, wxLANGUAGE_CZECH, wxLANGUAGE_GERMAN, wxLANGUAGE_ENGLISH, wxLANGUAGE_SPANISH, wxLANGUAGE_FRENCH, wxLANGUAGE_ITALIAN, wxLANGUAGE_HUNGARIAN, wxLANGUAGE_DUTCH, wxLANGUAGE_NORWEGIAN_BOKMAL, wxLANGUAGE_POLISH, wxLANGUAGE_PORTUGUESE, wxLANGUAGE_PORTUGUESE_BRAZILIAN, wxLANGUAGE_SERBIAN, wxLANGUAGE_SWEDISH, wxLANGUAGE_TURKISH, wxLANGUAGE_GREEK, wxLANGUAGE_RUSSIAN, wxLANGUAGE_HEBREW, wxLANGUAGE_ARABIC, wxLANGUAGE_FARSI, wxLANGUAGE_KOREAN, wxLANGUAGE_JAPANESE, wxLANGUAGE_CHINESE_SIMPLIFIED, wxLANGUAGE_CHINESE_TRADITIONAL, }; // Strings for Device Selections #define DEV_NONE_STR _trans("") #define DEV_DUMMY_STR _trans("Dummy") #define EXIDEV_MEMCARD_STR _trans("Memory Card") #define EXIDEV_MEMDIR_STR _trans("GCI Folder") #define EXIDEV_MIC_STR _trans("Mic") #define EXIDEV_BBA_STR "BBA" #define EXIDEV_AGP_STR "Advance Game Port" #define EXIDEV_AM_BB_STR _trans("AM-Baseboard") #define EXIDEV_GECKO_STR "USBGecko" #ifdef WIN32 //only used with xgettext to be picked up as translatable string. //win32 does not have wx on its path, the provided wxALL_FILES //translation does not work there. #define unusedALL_FILES wxTRANSLATE("All files (*.*)|*.*"); #endif BEGIN_EVENT_TABLE(CConfigMain, wxDialog) EVT_CLOSE(CConfigMain::OnClose) EVT_BUTTON(wxID_OK, CConfigMain::OnOk) EVT_CHECKBOX(ID_CPUTHREAD, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_IDLESKIP, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_ENABLECHEATS, CConfigMain::CoreSettingsChanged) EVT_CHOICE(ID_FRAMELIMIT, CConfigMain::CoreSettingsChanged) EVT_RADIOBOX(ID_CPUENGINE, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_NTSCJ, CConfigMain::CoreSettingsChanged) EVT_SLIDER(ID_OVERCLOCK, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_ENABLEOVERCLOCK, CConfigMain::CoreSettingsChanged) EVT_RADIOBOX(ID_DSPENGINE, CConfigMain::AudioSettingsChanged) EVT_CHECKBOX(ID_ENABLE_THROTTLE, CConfigMain::AudioSettingsChanged) EVT_CHECKBOX(ID_DPL2DECODER, CConfigMain::AudioSettingsChanged) EVT_CHOICE(ID_BACKEND, CConfigMain::AudioSettingsChanged) EVT_SLIDER(ID_VOLUME, CConfigMain::AudioSettingsChanged) EVT_CHECKBOX(ID_INTERFACE_CONFIRMSTOP, CConfigMain::DisplaySettingsChanged) EVT_CHECKBOX(ID_INTERFACE_USEPANICHANDLERS, CConfigMain::DisplaySettingsChanged) EVT_CHECKBOX(ID_INTERFACE_ONSCREENDISPLAYMESSAGES, CConfigMain::DisplaySettingsChanged) EVT_CHOICE(ID_INTERFACE_LANG, CConfigMain::DisplaySettingsChanged) EVT_BUTTON(ID_HOTKEY_CONFIG, CConfigMain::DisplaySettingsChanged) EVT_CHOICE(ID_GC_SRAM_LNG, CConfigMain::GCSettingsChanged) EVT_CHECKBOX(ID_GC_ALWAYS_HLE_BS2, CConfigMain::GCSettingsChanged) EVT_CHOICE(ID_GC_EXIDEVICE_SLOTA, CConfigMain::GCSettingsChanged) EVT_BUTTON(ID_GC_EXIDEVICE_SLOTA_PATH, CConfigMain::GCSettingsChanged) EVT_CHOICE(ID_GC_EXIDEVICE_SLOTB, CConfigMain::GCSettingsChanged) EVT_BUTTON(ID_GC_EXIDEVICE_SLOTB_PATH, CConfigMain::GCSettingsChanged) EVT_CHOICE(ID_GC_EXIDEVICE_SP1, CConfigMain::GCSettingsChanged) EVT_CHECKBOX(ID_WII_IPL_SSV, CConfigMain::WiiSettingsChanged) EVT_CHECKBOX(ID_WII_IPL_E60, CConfigMain::WiiSettingsChanged) EVT_CHOICE(ID_WII_IPL_AR, CConfigMain::WiiSettingsChanged) EVT_CHOICE(ID_WII_IPL_LNG, CConfigMain::WiiSettingsChanged) EVT_CHECKBOX(ID_WII_SD_CARD, CConfigMain::WiiSettingsChanged) EVT_CHECKBOX(ID_WII_KEYBOARD, CConfigMain::WiiSettingsChanged) EVT_LISTBOX(ID_ISOPATHS, CConfigMain::ISOPathsSelectionChanged) EVT_CHECKBOX(ID_RECURSIVEISOPATH, CConfigMain::RecursiveDirectoryChanged) EVT_BUTTON(ID_ADDISOPATH, CConfigMain::AddRemoveISOPaths) EVT_BUTTON(ID_REMOVEISOPATH, CConfigMain::AddRemoveISOPaths) EVT_FILEPICKER_CHANGED(ID_DEFAULTISO, CConfigMain::DefaultISOChanged) EVT_DIRPICKER_CHANGED(ID_DVDROOT, CConfigMain::DVDRootChanged) EVT_FILEPICKER_CHANGED(ID_APPLOADERPATH, CConfigMain::ApploaderPathChanged) EVT_DIRPICKER_CHANGED(ID_NANDROOT, CConfigMain::NANDRootChanged) END_EVENT_TABLE() CConfigMain::CConfigMain(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& position, const wxSize& size, long style) : wxDialog(parent, id, title, position, size, style) { // Control refreshing of the ISOs list bRefreshList = false; CreateGUIControls(); // Update selected ISO paths for (const std::string& folder : SConfig::GetInstance().m_ISOFolder) { ISOPaths->Append(StrToWxStr(folder)); } } CConfigMain::~CConfigMain() { } void CConfigMain::SetSelectedTab(int tab) { // TODO : this is just a quick and dirty way to do it, possible cleanup switch (tab) { case ID_AUDIOPAGE: Notebook->SetSelection(2); break; } } // Used to restrict changing of some options while emulator is running void CConfigMain::UpdateGUI() { if (Core::IsRunning()) { // Disable the Core stuff on GeneralPage CPUThread->Disable(); SkipIdle->Disable(); EnableCheats->Disable(); CPUEngine->Disable(); ForceNTSCJ->Disable(); // Disable stuff on AudioPage DSPEngine->Disable(); DPL2Decoder->Disable(); Latency->Disable(); // Disable stuff on GamecubePage GCSystemLang->Disable(); GCAlwaysHLE_BS2->Disable(); // Disable stuff on WiiPage WiiScreenSaver->Disable(); WiiPAL60->Disable(); WiiAspectRatio->Disable(); WiiSystemLang->Disable(); // Disable stuff on PathsPage PathsPage->Disable(); } } void CConfigMain::InitializeGUILists() { // General page // Framelimit arrayStringFor_Framelimit.Add(_("Off")); arrayStringFor_Framelimit.Add(_("Auto")); for (int i = 5; i <= 120; i += 5) // from 5 to 120 arrayStringFor_Framelimit.Add(wxString::Format("%i", i)); // Emulator Engine for (const CPUCore& CPUCores_a : CPUCores) arrayStringFor_CPUEngine.Add(wxGetTranslation(CPUCores_a.name)); // DSP Engine arrayStringFor_DSPEngine.Add(_("DSP HLE emulation (fast)")); arrayStringFor_DSPEngine.Add(_("DSP LLE recompiler")); arrayStringFor_DSPEngine.Add(_("DSP LLE interpreter (slow)")); // GameCube page // GC Language arrayStrings arrayStringFor_GCSystemLang.Add(_("English")); arrayStringFor_GCSystemLang.Add(_("German")); arrayStringFor_GCSystemLang.Add(_("French")); arrayStringFor_GCSystemLang.Add(_("Spanish")); arrayStringFor_GCSystemLang.Add(_("Italian")); arrayStringFor_GCSystemLang.Add(_("Dutch")); // Wii page // Sensorbar Position arrayStringFor_WiiSensBarPos.Add(_("Bottom")); arrayStringFor_WiiSensBarPos.Add(_("Top")); // Aspect ratio arrayStringFor_WiiAspectRatio.Add("4:3"); arrayStringFor_WiiAspectRatio.Add("16:9"); // Wii Language arrayStrings arrayStringFor_WiiSystemLang = arrayStringFor_GCSystemLang; arrayStringFor_WiiSystemLang.Insert(_("Japanese"), 0); arrayStringFor_WiiSystemLang.Add(_("Simplified Chinese")); arrayStringFor_WiiSystemLang.Add(_("Traditional Chinese")); arrayStringFor_WiiSystemLang.Add(_("Korean")); // GUI language arrayStrings // keep these in sync with the langIds array at the beginning of this file arrayStringFor_InterfaceLang.Add(_("")); arrayStringFor_InterfaceLang.Add(L"Catal\u00E0"); // Catalan arrayStringFor_InterfaceLang.Add(L"\u010Ce\u0161tina"); // Czech arrayStringFor_InterfaceLang.Add(L"Deutsch"); // German arrayStringFor_InterfaceLang.Add(L"English"); // English arrayStringFor_InterfaceLang.Add(L"Espa\u00F1ol"); // Spanish arrayStringFor_InterfaceLang.Add(L"Fran\u00E7ais"); // French arrayStringFor_InterfaceLang.Add(L"Italiano"); // Italian arrayStringFor_InterfaceLang.Add(L"Magyar"); // Hungarian arrayStringFor_InterfaceLang.Add(L"Nederlands"); // Dutch arrayStringFor_InterfaceLang.Add(L"Norsk bokm\u00E5l"); // Norwegian arrayStringFor_InterfaceLang.Add(L"Polski"); // Polish arrayStringFor_InterfaceLang.Add(L"Portugu\u00EAs"); // Portuguese arrayStringFor_InterfaceLang.Add(L"Portugu\u00EAs (Brasil)"); // Portuguese (Brazil) arrayStringFor_InterfaceLang.Add(L"Srpski"); // Serbian arrayStringFor_InterfaceLang.Add(L"Svenska"); // Swedish arrayStringFor_InterfaceLang.Add(L"T\u00FCrk\u00E7e"); // Turkish arrayStringFor_InterfaceLang.Add(L"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC"); // Greek arrayStringFor_InterfaceLang.Add(L"\u0420\u0443\u0441\u0441\u043A\u0438\u0439"); // Russian arrayStringFor_InterfaceLang.Add(L"\u05E2\u05D1\u05E8\u05D9\u05EA"); // Hebrew arrayStringFor_InterfaceLang.Add(L"\u0627\u0644\u0639\u0631\u0628\u064A\u0629"); // Arabic arrayStringFor_InterfaceLang.Add(L"\u0641\u0627\u0631\u0633\u06CC"); // Farsi arrayStringFor_InterfaceLang.Add(L"\uD55C\uAD6D\uC5B4"); // Korean arrayStringFor_InterfaceLang.Add(L"\u65E5\u672C\u8A9E"); // Japanese arrayStringFor_InterfaceLang.Add(L"\u7B80\u4F53\u4E2D\u6587"); // Simplified Chinese arrayStringFor_InterfaceLang.Add(L"\u7E41\u9AD4\u4E2D\u6587"); // Traditional Chinese } void CConfigMain::InitializeGUIValues() { const SCoreStartupParameter& startup_params = SConfig::GetInstance().m_LocalCoreStartupParameter; // General - Basic CPUThread->SetValue(startup_params.bCPUThread); SkipIdle->SetValue(startup_params.bSkipIdle); EnableCheats->SetValue(startup_params.bEnableCheats); Framelimit->SetSelection(SConfig::GetInstance().m_Framelimit); int ocFactor = (int)(log2f(SConfig::GetInstance().m_OCFactor) * 25.f + 100.f + 0.5f); EnableOC->SetValue(SConfig::GetInstance().m_OCEnable); OCSlider->SetValue(ocFactor); UpdateCPUClock(); // General - Advanced for (unsigned int a = 0; a < (sizeof(CPUCores) / sizeof(CPUCore)); ++a) if (CPUCores[a].CPUid == startup_params.iCPUCore) CPUEngine->SetSelection(a); ForceNTSCJ->SetValue(startup_params.bForceNTSCJ); // Display - Interface ConfirmStop->SetValue(startup_params.bConfirmStop); UsePanicHandlers->SetValue(startup_params.bUsePanicHandlers); OnScreenDisplayMessages->SetValue(startup_params.bOnScreenDisplayMessages); // need redesign for (unsigned int i = 0; i < sizeof(langIds) / sizeof(wxLanguage); i++) { if (langIds[i] == SConfig::GetInstance().m_InterfaceLanguage) { InterfaceLang->SetSelection(i); break; } } // Audio DSP Engine if (startup_params.bDSPHLE) DSPEngine->SetSelection(0); else DSPEngine->SetSelection(SConfig::GetInstance().m_DSPEnableJIT ? 1 : 2); // Audio VolumeSlider->Enable(SupportsVolumeChanges(SConfig::GetInstance().sBackend)); VolumeSlider->SetValue(SConfig::GetInstance().m_Volume); VolumeText->SetLabel(wxString::Format("%d %%", SConfig::GetInstance().m_Volume)); DPL2Decoder->Enable(std::string(SConfig::GetInstance().sBackend) == BACKEND_OPENAL || std::string(SConfig::GetInstance().sBackend) == BACKEND_PULSEAUDIO); DPL2Decoder->SetValue(startup_params.bDPL2Decoder); Latency->Enable(std::string(SConfig::GetInstance().sBackend) == BACKEND_OPENAL); Latency->SetValue(startup_params.iLatency); // add backends to the list AddAudioBackends(); // GameCube - IPL GCSystemLang->SetSelection(startup_params.SelectedLanguage); GCAlwaysHLE_BS2->SetValue(startup_params.bHLE_BS2); // GameCube - Devices wxArrayString SlotDevices; SlotDevices.Add(_(DEV_NONE_STR)); SlotDevices.Add(_(DEV_DUMMY_STR)); SlotDevices.Add(_(EXIDEV_MEMCARD_STR)); SlotDevices.Add(_(EXIDEV_MEMDIR_STR)); SlotDevices.Add(_(EXIDEV_GECKO_STR)); SlotDevices.Add(_(EXIDEV_AGP_STR)); #if HAVE_PORTAUDIO SlotDevices.Add(_(EXIDEV_MIC_STR)); #endif wxArrayString SP1Devices; SP1Devices.Add(_(DEV_NONE_STR)); SP1Devices.Add(_(DEV_DUMMY_STR)); SP1Devices.Add(_(EXIDEV_BBA_STR)); SP1Devices.Add(_(EXIDEV_AM_BB_STR)); for (int i = 0; i < 3; ++i) { bool isMemcard = false; // Add strings to the wxChoice list, the third wxChoice is the SP1 slot if (i == 2) GCEXIDevice[i]->Append(SP1Devices); else GCEXIDevice[i]->Append(SlotDevices); switch (SConfig::GetInstance().m_EXIDevice[i]) { case EXIDEVICE_NONE: GCEXIDevice[i]->SetStringSelection(SlotDevices[0]); break; case EXIDEVICE_MEMORYCARD: isMemcard = GCEXIDevice[i]->SetStringSelection(SlotDevices[2]); break; case EXIDEVICE_MEMORYCARDFOLDER: GCEXIDevice[i]->SetStringSelection(SlotDevices[3]); break; case EXIDEVICE_GECKO: GCEXIDevice[i]->SetStringSelection(SlotDevices[4]); break; case EXIDEVICE_AGP: isMemcard = GCEXIDevice[i]->SetStringSelection(SlotDevices[5]); break; case EXIDEVICE_MIC: GCEXIDevice[i]->SetStringSelection(SlotDevices[6]); break; case EXIDEVICE_ETH: GCEXIDevice[i]->SetStringSelection(SP1Devices[2]); break; case EXIDEVICE_AM_BASEBOARD: GCEXIDevice[i]->SetStringSelection(SP1Devices[3]); break; case EXIDEVICE_DUMMY: default: GCEXIDevice[i]->SetStringSelection(SlotDevices[1]); break; } if (!isMemcard && i < 2) GCMemcardPath[i]->Disable(); } // Wii - Misc WiiScreenSaver->SetValue(!!SConfig::GetInstance().m_SYSCONF->GetData("IPL.SSV")); WiiPAL60->SetValue(!!SConfig::GetInstance().m_SYSCONF->GetData("IPL.E60")); WiiAspectRatio->SetSelection(SConfig::GetInstance().m_SYSCONF->GetData("IPL.AR")); WiiSystemLang->SetSelection(SConfig::GetInstance().m_SYSCONF->GetData("IPL.LNG")); // Wii - Devices WiiSDCard->SetValue(SConfig::GetInstance().m_WiiSDCard); WiiKeyboard->SetValue(SConfig::GetInstance().m_WiiKeyboard); // Paths RecursiveISOPath->SetValue(SConfig::GetInstance().m_RecursiveISOFolder); DefaultISO->SetPath(StrToWxStr(startup_params.m_strDefaultISO)); DVDRoot->SetPath(StrToWxStr(startup_params.m_strDVDRoot)); ApploaderPath->SetPath(StrToWxStr(startup_params.m_strApploader)); NANDRoot->SetPath(StrToWxStr(SConfig::GetInstance().m_NANDPath)); } void CConfigMain::InitializeGUITooltips() { // General - Basic CPUThread->SetToolTip(_("Splits the CPU and GPU threads so they can be run on separate cores.\nProvides major speed improvements on most modern PCs, but can cause occasional crashes/glitches.")); SkipIdle->SetToolTip(_("Attempt to detect and skip wait-loops.\nIf unsure, leave this checked.")); EnableCheats->SetToolTip(_("Enables the use of Action Replay and Gecko cheats.")); Framelimit->SetToolTip(_("Limits the game speed to the specified number of frames per second (full speed is 60 for NTSC and 50 for PAL).")); // General - Advanced ForceNTSCJ->SetToolTip(_("Forces NTSC-J mode for using the Japanese ROM font.\nIf left unchecked, Dolphin defaults to NTSC-U and automatically enables this setting when playing Japanese games.")); // Display - Interface ConfirmStop->SetToolTip(_("Show a confirmation box before stopping a game.")); UsePanicHandlers->SetToolTip(_("Show a message box when a potentially serious error has occurred.\nDisabling this may avoid annoying and non-fatal messages, but it may result in major crashes having no explanation at all.")); OnScreenDisplayMessages->SetToolTip(_("Display messages over the emulation screen area.\nThese messages include memory card writes, video backend and CPU information, and JIT cache clearing.")); InterfaceLang->SetToolTip(_("Change the language of the user interface.\nRequires restart.")); // Audio - Backend BackendSelection->SetToolTip(_("Changing this will have no effect while the emulator is running.")); // GameCube - IPL GCSystemLang->SetToolTip(_("Sets the GameCube system language.")); // GameCube - Devices GCEXIDevice[2]->SetToolTip(_("Serial Port 1 - This is the port which devices such as the net adapter use.")); // Wii - Misc WiiScreenSaver->SetToolTip(_("Dims the screen after five minutes of inactivity.")); WiiPAL60->SetToolTip(_("Sets the Wii display mode to 60Hz (480i) instead of 50Hz (576i) for PAL games.\nMay not work for all games.")); WiiSystemLang->SetToolTip(_("Sets the Wii system language.")); // Wii - Devices WiiSDCard->SetToolTip(_("Saved to /Wii/sd.raw (default size is 128mb)")); WiiKeyboard->SetToolTip(_("May cause slow down in Wii Menu and some games.")); #if defined(__APPLE__) DPL2Decoder->SetToolTip(_("Enables Dolby Pro Logic II emulation using 5.1 surround. Not available on OS X.")); #else DPL2Decoder->SetToolTip(_("Enables Dolby Pro Logic II emulation using 5.1 surround. OpenAL or Pulse backends only.")); #endif Latency->SetToolTip(_("Sets the latency (in ms). Higher values may reduce audio crackling. OpenAL backend only.")); } void CConfigMain::CreateGUIControls() { InitializeGUILists(); // Create the notebook and pages Notebook = new wxNotebook(this, ID_NOTEBOOK); wxPanel* const GeneralPage = new wxPanel(Notebook, ID_GENERALPAGE); wxPanel* const DisplayPage = new wxPanel(Notebook, ID_DISPLAYPAGE); wxPanel* const AudioPage = new wxPanel(Notebook, ID_AUDIOPAGE); wxPanel* const GamecubePage = new wxPanel(Notebook, ID_GAMECUBEPAGE); wxPanel* const WiiPage = new wxPanel(Notebook, ID_WIIPAGE); wxPanel* const AdvancedPage = new wxPanel(Notebook, ID_ADVANCEDPAGE); PathsPage = new wxPanel(Notebook, ID_PATHSPAGE); Notebook->AddPage(GeneralPage, _("General")); Notebook->AddPage(DisplayPage, _("Interface")); Notebook->AddPage(AudioPage, _("Audio")); Notebook->AddPage(GamecubePage, _("GameCube")); Notebook->AddPage(WiiPage, _("Wii")); Notebook->AddPage(PathsPage, _("Paths")); Notebook->AddPage(AdvancedPage, _("Advanced")); // General page // Core Settings - Basic CPUThread = new wxCheckBox(GeneralPage, ID_CPUTHREAD, _("Enable Dual Core (speedup)")); SkipIdle = new wxCheckBox(GeneralPage, ID_IDLESKIP, _("Enable Idle Skipping (speedup)")); EnableCheats = new wxCheckBox(GeneralPage, ID_ENABLECHEATS, _("Enable Cheats")); // Framelimit Framelimit = new wxChoice(GeneralPage, ID_FRAMELIMIT, wxDefaultPosition, wxDefaultSize, arrayStringFor_Framelimit); // Core Settings - Advanced CPUEngine = new wxRadioBox(GeneralPage, ID_CPUENGINE, _("CPU Emulator Engine"), wxDefaultPosition, wxDefaultSize, arrayStringFor_CPUEngine, 0, wxRA_SPECIFY_ROWS); ForceNTSCJ = new wxCheckBox(GeneralPage, ID_NTSCJ, _("Force Console as NTSC-J")); // Populate the General settings wxBoxSizer* sFramelimit = new wxBoxSizer(wxHORIZONTAL); sFramelimit->Add(TEXT_BOX(GeneralPage, _("Framelimit:")), 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM, 5); sFramelimit->Add(Framelimit, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5); wxStaticBoxSizer* const sbBasic = new wxStaticBoxSizer(wxVERTICAL, GeneralPage, _("Basic Settings")); sbBasic->Add(CPUThread, 0, wxALL, 5); sbBasic->Add(SkipIdle, 0, wxALL, 5); sbBasic->Add(EnableCheats, 0, wxALL, 5); sbBasic->Add(sFramelimit); wxStaticBoxSizer* const sbAdvanced = new wxStaticBoxSizer(wxVERTICAL, GeneralPage, _("Advanced Settings")); sbAdvanced->Add(CPUEngine, 0, wxALL, 5); sbAdvanced->Add(ForceNTSCJ, 0, wxALL, 5); wxBoxSizer* const sGeneralPage = new wxBoxSizer(wxVERTICAL); sGeneralPage->Add(sbBasic, 0, wxEXPAND | wxALL, 5); sGeneralPage->Add(sbAdvanced, 0, wxEXPAND | wxALL, 5); GeneralPage->SetSizer(sGeneralPage); // Interface Language InterfaceLang = new wxChoice(DisplayPage, ID_INTERFACE_LANG, wxDefaultPosition, wxDefaultSize, arrayStringFor_InterfaceLang); // Hotkey configuration HotkeyConfig = new wxButton(DisplayPage, ID_HOTKEY_CONFIG, _("Hotkeys"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); // Interface settings ConfirmStop = new wxCheckBox(DisplayPage, ID_INTERFACE_CONFIRMSTOP, _("Confirm on Stop")); UsePanicHandlers = new wxCheckBox(DisplayPage, ID_INTERFACE_USEPANICHANDLERS, _("Use Panic Handlers")); OnScreenDisplayMessages = new wxCheckBox(DisplayPage, ID_INTERFACE_ONSCREENDISPLAYMESSAGES, _("On-Screen Display Messages")); wxBoxSizer* sInterface = new wxBoxSizer(wxHORIZONTAL); sInterface->Add(TEXT_BOX(DisplayPage, _("Language:")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); sInterface->Add(InterfaceLang, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); sInterface->AddStretchSpacer(); sInterface->Add(HotkeyConfig, 0, wxALIGN_RIGHT | wxALL, 5); // theme selection auto const theme_selection = new wxChoice(DisplayPage, wxID_ANY); CFileSearch::XStringVector theme_dirs; theme_dirs.push_back(File::GetUserPath(D_THEMES_IDX)); theme_dirs.push_back(File::GetSysDirectory() + THEMES_DIR); CFileSearch cfs(CFileSearch::XStringVector(1, "*"), theme_dirs); auto const& sv = cfs.GetFileNames(); std::for_each(sv.begin(), sv.end(), [theme_selection](const std::string& filename) { std::string name, ext; SplitPath(filename, nullptr, &name, &ext); name += ext; auto const wxname = StrToWxStr(name); if (-1 == theme_selection->FindString(wxname)) theme_selection->Append(wxname); }); theme_selection->SetStringSelection(StrToWxStr(SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name)); // std::function = avoid error on msvc theme_selection->Bind(wxEVT_CHOICE, std::function([theme_selection](wxEvent&) { SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name = WxStrToStr(theme_selection->GetStringSelection()); main_frame->InitBitmaps(); main_frame->UpdateGameList(); })); auto const scInterface = new wxBoxSizer(wxHORIZONTAL); scInterface->Add(TEXT_BOX(DisplayPage, _("Theme:")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); scInterface->Add(theme_selection, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); scInterface->AddStretchSpacer(); sbInterface = new wxStaticBoxSizer(wxVERTICAL, DisplayPage, _("Interface Settings")); sbInterface->Add(ConfirmStop, 0, wxALL, 5); sbInterface->Add(UsePanicHandlers, 0, wxALL, 5); sbInterface->Add(OnScreenDisplayMessages, 0, wxALL, 5); sbInterface->Add(scInterface, 0, wxEXPAND | wxALL, 5); sbInterface->Add(sInterface, 0, wxEXPAND | wxALL, 5); sDisplayPage = new wxBoxSizer(wxVERTICAL); sDisplayPage->Add(sbInterface, 0, wxEXPAND | wxALL, 5); DisplayPage->SetSizer(sDisplayPage); // Audio page DSPEngine = new wxRadioBox(AudioPage, ID_DSPENGINE, _("DSP Emulator Engine"), wxDefaultPosition, wxDefaultSize, arrayStringFor_DSPEngine, 0, wxRA_SPECIFY_ROWS); DPL2Decoder = new wxCheckBox(AudioPage, ID_DPL2DECODER, _("Dolby Pro Logic II decoder")); VolumeSlider = new wxSlider(AudioPage, ID_VOLUME, 0, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_VERTICAL | wxSL_INVERSE); VolumeText = new wxStaticText(AudioPage, wxID_ANY, ""); BackendSelection = new wxChoice(AudioPage, ID_BACKEND, wxDefaultPosition, wxDefaultSize, wxArrayBackends, 0, wxDefaultValidator, wxEmptyString); Latency = new wxSpinCtrl(AudioPage, ID_LATENCY, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 30); Latency->Bind(wxEVT_SPINCTRL, &CConfigMain::AudioSettingsChanged, this); if (Core::IsRunning()) { Latency->Disable(); BackendSelection->Disable(); DPL2Decoder->Disable(); } // Create sizer and add items to dialog wxStaticBoxSizer *sbAudioSettings = new wxStaticBoxSizer(wxVERTICAL, AudioPage, _("Sound Settings")); sbAudioSettings->Add(DSPEngine, 0, wxALL | wxEXPAND, 5); sbAudioSettings->Add(DPL2Decoder, 0, wxALL, 5); wxStaticBoxSizer *sbVolume = new wxStaticBoxSizer(wxVERTICAL, AudioPage, _("Volume")); sbVolume->Add(VolumeSlider, 1, wxLEFT | wxRIGHT, 13); sbVolume->Add(VolumeText, 0, wxALIGN_CENTER | wxALL, 5); wxGridBagSizer *sBackend = new wxGridBagSizer(); sBackend->Add(TEXT_BOX(AudioPage, _("Audio Backend:")), wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5); sBackend->Add(BackendSelection, wxGBPosition(0, 1), wxDefaultSpan, wxALL, 5); sBackend->Add(TEXT_BOX(AudioPage, _("Latency:")), wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5); sBackend->Add(Latency, wxGBPosition(1, 1), wxDefaultSpan, wxALL, 5); wxStaticBoxSizer *sbBackend = new wxStaticBoxSizer(wxHORIZONTAL, AudioPage, _("Backend Settings")); sbBackend->Add(sBackend, 0, wxEXPAND); wxBoxSizer *sAudio = new wxBoxSizer(wxHORIZONTAL); sAudio->Add(sbAudioSettings, 1, wxEXPAND | wxALL, 5); sAudio->Add(sbVolume, 0, wxEXPAND | wxALL, 5); sAudioPage = new wxBoxSizer(wxVERTICAL); sAudioPage->Add(sAudio, 0, wxALL | wxEXPAND); sAudioPage->Add(sbBackend, 0, wxALL | wxEXPAND, 5); AudioPage->SetSizerAndFit(sAudioPage); // GameCube page // IPL settings GCSystemLang = new wxChoice(GamecubePage, ID_GC_SRAM_LNG, wxDefaultPosition, wxDefaultSize, arrayStringFor_GCSystemLang); GCAlwaysHLE_BS2 = new wxCheckBox(GamecubePage, ID_GC_ALWAYS_HLE_BS2, _("Skip BIOS")); if (!File::Exists(File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + USA_DIR + DIR_SEP GC_IPL) && !File::Exists(File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + USA_DIR + DIR_SEP GC_IPL) && !File::Exists(File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + JAP_DIR + DIR_SEP GC_IPL) && !File::Exists(File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + JAP_DIR + DIR_SEP GC_IPL) && !File::Exists(File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + EUR_DIR + DIR_SEP GC_IPL) && !File::Exists(File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + EUR_DIR + DIR_SEP GC_IPL)) { GCAlwaysHLE_BS2->Disable(); GCAlwaysHLE_BS2->SetToolTip(_("Put BIOS roms in User/GC/{region}.")); } // Device settings // EXI Devices wxStaticText* GCEXIDeviceText[3]; GCEXIDeviceText[0] = TEXT_BOX(GamecubePage, _("Slot A")); GCEXIDeviceText[1] = TEXT_BOX(GamecubePage, _("Slot B")); GCEXIDeviceText[2] = TEXT_BOX(GamecubePage, "SP1"); GCEXIDevice[0] = new wxChoice(GamecubePage, ID_GC_EXIDEVICE_SLOTA); GCEXIDevice[1] = new wxChoice(GamecubePage, ID_GC_EXIDEVICE_SLOTB); GCEXIDevice[2] = new wxChoice(GamecubePage, ID_GC_EXIDEVICE_SP1); GCMemcardPath[0] = new wxButton(GamecubePage, ID_GC_EXIDEVICE_SLOTA_PATH, "...", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); GCMemcardPath[1] = new wxButton(GamecubePage, ID_GC_EXIDEVICE_SLOTB_PATH, "...", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); // Populate the GameCube page sGamecubeIPLSettings = new wxGridBagSizer(); sGamecubeIPLSettings->Add(GCAlwaysHLE_BS2, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); sGamecubeIPLSettings->Add(TEXT_BOX(GamecubePage, _("System Language:")), wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM, 5); sGamecubeIPLSettings->Add(GCSystemLang, wxGBPosition(1, 1), wxDefaultSpan, wxLEFT | wxRIGHT | wxBOTTOM, 5); sbGamecubeIPLSettings = new wxStaticBoxSizer(wxVERTICAL, GamecubePage, _("IPL Settings")); sbGamecubeIPLSettings->Add(sGamecubeIPLSettings); wxStaticBoxSizer *sbGamecubeDeviceSettings = new wxStaticBoxSizer(wxVERTICAL, GamecubePage, _("Device Settings")); wxGridBagSizer* sbGamecubeEXIDevSettings = new wxGridBagSizer(10, 10); for (int i = 0; i < 3; ++i) { sbGamecubeEXIDevSettings->Add(GCEXIDeviceText[i], wxGBPosition(i, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); sbGamecubeEXIDevSettings->Add(GCEXIDevice[i], wxGBPosition(i, 1), wxGBSpan(1, (i < 2) ? 1 : 2), wxALIGN_CENTER_VERTICAL); if (i < 2) sbGamecubeEXIDevSettings->Add(GCMemcardPath[i], wxGBPosition(i, 2), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); if (NetPlay::IsNetPlayRunning()) GCEXIDevice[i]->Disable(); } sbGamecubeDeviceSettings->Add(sbGamecubeEXIDevSettings, 0, wxALL, 5); sGamecubePage = new wxBoxSizer(wxVERTICAL); sGamecubePage->Add(sbGamecubeIPLSettings, 0, wxEXPAND | wxALL, 5); sGamecubePage->Add(sbGamecubeDeviceSettings, 0, wxEXPAND | wxALL, 5); GamecubePage->SetSizer(sGamecubePage); // Wii page // Misc Settings WiiScreenSaver = new wxCheckBox(WiiPage, ID_WII_IPL_SSV, _("Enable Screen Saver")); WiiPAL60 = new wxCheckBox(WiiPage, ID_WII_IPL_E60, _("Use PAL60 Mode (EuRGB60)")); WiiAspectRatio = new wxChoice(WiiPage, ID_WII_IPL_AR, wxDefaultPosition, wxDefaultSize, arrayStringFor_WiiAspectRatio); WiiSystemLang = new wxChoice(WiiPage, ID_WII_IPL_LNG, wxDefaultPosition, wxDefaultSize, arrayStringFor_WiiSystemLang); // Device Settings WiiSDCard = new wxCheckBox(WiiPage, ID_WII_SD_CARD, _("Insert SD Card")); WiiKeyboard = new wxCheckBox(WiiPage, ID_WII_KEYBOARD, _("Connect USB Keyboard")); // Populate the Wii Page sWiiIPLSettings = new wxGridBagSizer(); sWiiIPLSettings->Add(WiiScreenSaver, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); sWiiIPLSettings->Add(WiiPAL60, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); sWiiIPLSettings->Add(TEXT_BOX(WiiPage, _("Aspect Ratio:")), wxGBPosition(2, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5); sWiiIPLSettings->Add(WiiAspectRatio, wxGBPosition(2, 1), wxDefaultSpan, wxALL, 5); sWiiIPLSettings->Add(TEXT_BOX(WiiPage, _("System Language:")), wxGBPosition(3, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5); sWiiIPLSettings->Add(WiiSystemLang, wxGBPosition(3, 1), wxDefaultSpan, wxALL, 5); sbWiiIPLSettings = new wxStaticBoxSizer(wxVERTICAL, WiiPage, _("Misc Settings")); sbWiiIPLSettings->Add(sWiiIPLSettings); sbWiiDeviceSettings = new wxStaticBoxSizer(wxVERTICAL, WiiPage, _("Device Settings")); sbWiiDeviceSettings->Add(WiiSDCard, 0, wxALL, 5); sbWiiDeviceSettings->Add(WiiKeyboard, 0, wxALL, 5); sWiiPage = new wxBoxSizer(wxVERTICAL); sWiiPage->Add(sbWiiIPLSettings, 0, wxEXPAND | wxALL, 5); sWiiPage->Add(sbWiiDeviceSettings, 0, wxEXPAND | wxALL, 5); WiiPage->SetSizer(sWiiPage); // Paths page ISOPaths = new wxListBox(PathsPage, ID_ISOPATHS, wxDefaultPosition, wxDefaultSize, arrayStringFor_ISOPaths, wxLB_SINGLE); RecursiveISOPath = new wxCheckBox(PathsPage, ID_RECURSIVEISOPATH, _("Search Subfolders")); AddISOPath = new wxButton(PathsPage, ID_ADDISOPATH, _("Add...")); RemoveISOPath = new wxButton(PathsPage, ID_REMOVEISOPATH, _("Remove")); RemoveISOPath->Disable(); DefaultISO = new wxFilePickerCtrl(PathsPage, ID_DEFAULTISO, wxEmptyString, _("Choose a default ISO:"), _("All GC/Wii files (elf, dol, gcm, iso, wbfs, ciso, gcz, wad)") + wxString::Format("|*.elf;*.dol;*.gcm;*.iso;*.wbfs;*.ciso;*.gcz;*.wad|%s", wxGetTranslation(wxALL_FILES)), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL | wxFLP_OPEN); DVDRoot = new wxDirPickerCtrl(PathsPage, ID_DVDROOT, wxEmptyString, _("Choose a DVD root directory:"), wxDefaultPosition, wxDefaultSize, wxDIRP_USE_TEXTCTRL); ApploaderPath = new wxFilePickerCtrl(PathsPage, ID_APPLOADERPATH, wxEmptyString, _("Choose file to use as apploader: (applies to discs constructed from directories only)"), _("apploader (.img)") + wxString::Format("|*.img|%s", wxGetTranslation(wxALL_FILES)), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL | wxFLP_OPEN); NANDRoot = new wxDirPickerCtrl(PathsPage, ID_NANDROOT, wxEmptyString, _("Choose a NAND root directory:"), wxDefaultPosition, wxDefaultSize, wxDIRP_USE_TEXTCTRL); // Populate the settings wxBoxSizer* sISOButtons = new wxBoxSizer(wxHORIZONTAL); sISOButtons->Add(RecursiveISOPath, 0, wxALL | wxALIGN_CENTER, 0); sISOButtons->AddStretchSpacer(); sISOButtons->Add(AddISOPath, 0, wxALL, 0); sISOButtons->Add(RemoveISOPath, 0, wxALL, 0); sbISOPaths = new wxStaticBoxSizer(wxVERTICAL, PathsPage, _("ISO Directories")); sbISOPaths->Add(ISOPaths, 1, wxEXPAND | wxALL, 0); sbISOPaths->Add(sISOButtons, 0, wxEXPAND | wxALL, 5); sOtherPaths = new wxGridBagSizer(); sOtherPaths->Add(TEXT_BOX(PathsPage, _("Default ISO:")), wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5); sOtherPaths->Add(DefaultISO, wxGBPosition(0, 1), wxDefaultSpan, wxEXPAND | wxALL, 5); sOtherPaths->Add(TEXT_BOX(PathsPage, _("DVD Root:")), wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5); sOtherPaths->Add(DVDRoot, wxGBPosition(1, 1), wxDefaultSpan, wxEXPAND | wxALL, 5); sOtherPaths->Add(TEXT_BOX(PathsPage, _("Apploader:")), wxGBPosition(2, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5); sOtherPaths->Add(ApploaderPath, wxGBPosition(2, 1), wxDefaultSpan, wxEXPAND | wxALL, 5); sOtherPaths->Add(TEXT_BOX(PathsPage, _("Wii NAND Root:")), wxGBPosition(3, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5); sOtherPaths->Add(NANDRoot, wxGBPosition(3, 1), wxDefaultSpan, wxEXPAND | wxALL, 5); sOtherPaths->AddGrowableCol(1); // Populate the Paths page sPathsPage = new wxBoxSizer(wxVERTICAL); sPathsPage->Add(sbISOPaths, 1, wxEXPAND | wxALL, 5); sPathsPage->Add(sOtherPaths, 0, wxEXPAND | wxALL, 5); PathsPage->SetSizer(sPathsPage); wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL); sMain->Add(Notebook, 1, wxEXPAND | wxALL, 5); sMain->Add(CreateButtonSizer(wxOK), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); wxStaticBoxSizer* sbCPUOptions = new wxStaticBoxSizer(wxVERTICAL, AdvancedPage, _("CPU Options")); wxBoxSizer* bOverclockEnable = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* bOverclock = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* bOverclockDesc = new wxBoxSizer(wxHORIZONTAL); EnableOC = new wxCheckBox(AdvancedPage, ID_ENABLEOVERCLOCK, _("Enable CPU Clock Override")); OCSlider = new wxSlider(AdvancedPage, ID_OVERCLOCK, 100, 0, 150, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL); wxStaticText* OCDescription = new wxStaticText(AdvancedPage, wxID_ANY, _("Higher values can make variable-framerate games\n" "run at a higher framerate, at the expense of CPU.\n" "Lower values can make variable-framerate games\n" "run at a lower framerate, saving CPU.\n\n" "WARNING: Changing this from the default (100%)\n" "can and will break games and cause glitches.\n" "Do so at your own risk. Please do not report\n" "bugs that occur with a non-default clock.\n")); OCText = new wxStaticText(AdvancedPage, wxID_ANY, ""); bOverclockEnable->Add(EnableOC); bOverclock->Add(OCSlider, 1, wxALL, 5); bOverclock->Add(OCText, 1, wxALL, 5); bOverclockDesc->Add(OCDescription, 1, wxALL, 5); sbCPUOptions->Add(bOverclockEnable); sbCPUOptions->Add(bOverclock); sbCPUOptions->Add(bOverclockDesc); wxBoxSizer* const sAdvancedPage = new wxBoxSizer(wxVERTICAL); sAdvancedPage->Add(sbCPUOptions, 0, wxEXPAND | wxALL, 5); AdvancedPage->SetSizer(sAdvancedPage); InitializeGUIValues(); InitializeGUITooltips(); UpdateGUI(); SetSizerAndFit(sMain); Center(); SetFocus(); } void CConfigMain::OnClose(wxCloseEvent& WXUNUSED(event)) { EndModal((bRefreshList) ? wxID_OK : wxID_CANCEL); } void CConfigMain::OnOk(wxCommandEvent& WXUNUSED(event)) { Close(); // Save the config. Dolphin crashes too often to only save the settings on closing SConfig::GetInstance().SaveSettings(); } void CConfigMain::UpdateCPUClock() { bool wii = SConfig::GetInstance().m_LocalCoreStartupParameter.bWii; int percent = (int)(roundf(SConfig::GetInstance().m_OCFactor * 100.f)); int clock = (int)(roundf(SConfig::GetInstance().m_OCFactor * (wii ? 729.f : 486.f))); OCText->SetLabel(SConfig::GetInstance().m_OCEnable ? wxString::Format("%d %% (%d mhz)", percent, clock) : ""); } // Core settings void CConfigMain::CoreSettingsChanged(wxCommandEvent& event) { SCoreStartupParameter& startup_params = SConfig::GetInstance().m_LocalCoreStartupParameter; switch (event.GetId()) { // Core - Basic case ID_CPUTHREAD: if (Core::IsRunning()) return; startup_params.bCPUThread = CPUThread->IsChecked(); break; case ID_IDLESKIP: startup_params.bSkipIdle = SkipIdle->IsChecked(); break; case ID_ENABLECHEATS: startup_params.bEnableCheats = EnableCheats->IsChecked(); break; case ID_FRAMELIMIT: SConfig::GetInstance().m_Framelimit = Framelimit->GetSelection(); break; // Core - Advanced case ID_CPUENGINE: startup_params.iCPUCore = CPUCores[CPUEngine->GetSelection()].CPUid; if (main_frame->g_pCodeWindow) { bool using_interp = (startup_params.iCPUCore == PowerPC::CORE_INTERPRETER); main_frame->g_pCodeWindow->GetMenuBar()->Check(IDM_INTERPRETER, using_interp); } break; case ID_NTSCJ: startup_params.bForceNTSCJ = ForceNTSCJ->IsChecked(); break; case ID_ENABLEOVERCLOCK: SConfig::GetInstance().m_OCEnable = EnableOC->IsChecked(); OCSlider->Enable(SConfig::GetInstance().m_OCEnable); UpdateCPUClock(); break; case ID_OVERCLOCK: // Vaguely exponential scaling? SConfig::GetInstance().m_OCFactor = exp2f((OCSlider->GetValue() - 100.f) / 25.f); UpdateCPUClock(); break; } } // Display and Interface settings void CConfigMain::DisplaySettingsChanged(wxCommandEvent& event) { switch (event.GetId()) { // Display - Interface case ID_INTERFACE_CONFIRMSTOP: SConfig::GetInstance().m_LocalCoreStartupParameter.bConfirmStop = ConfirmStop->IsChecked(); break; case ID_INTERFACE_USEPANICHANDLERS: SConfig::GetInstance().m_LocalCoreStartupParameter.bUsePanicHandlers = UsePanicHandlers->IsChecked(); SetEnableAlert(UsePanicHandlers->IsChecked()); break; case ID_INTERFACE_ONSCREENDISPLAYMESSAGES: SConfig::GetInstance().m_LocalCoreStartupParameter.bOnScreenDisplayMessages = OnScreenDisplayMessages->IsChecked(); SetEnableAlert(OnScreenDisplayMessages->IsChecked()); break; case ID_INTERFACE_LANG: if (SConfig::GetInstance().m_InterfaceLanguage != langIds[InterfaceLang->GetSelection()]) SuccessAlertT("You must restart Dolphin in order for the change to take effect."); SConfig::GetInstance().m_InterfaceLanguage = langIds[InterfaceLang->GetSelection()]; break; case ID_HOTKEY_CONFIG: { bool was_init = false; InputConfig* const hotkey_plugin = HotkeyManagerEmu::GetConfig(); // check if game is running if (g_controller_interface.IsInit()) { was_init = true; } else { #if defined(HAVE_X11) && HAVE_X11 Window win = X11Utils::XWindowFromHandle(GetHandle()); HotkeyManagerEmu::Initialize(reinterpret_cast(win)); #else HotkeyManagerEmu::Initialize(reinterpret_cast(GetHandle())); #endif } InputConfigDialog m_ConfigFrame(this, *hotkey_plugin, _("Dolphin Hotkeys")); m_ConfigFrame.ShowModal(); // if game isn't running if (!was_init) { HotkeyManagerEmu::Shutdown(); } } // Update the GUI in case menu accelerators were changed main_frame->UpdateGUI(); break; } } void CConfigMain::AudioSettingsChanged(wxCommandEvent& event) { switch (event.GetId()) { case ID_DSPENGINE: SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPHLE = DSPEngine->GetSelection() == 0; SConfig::GetInstance().m_DSPEnableJIT = DSPEngine->GetSelection() == 1; AudioCommon::UpdateSoundStream(); break; case ID_VOLUME: SConfig::GetInstance().m_Volume = VolumeSlider->GetValue(); AudioCommon::UpdateSoundStream(); VolumeText->SetLabel(wxString::Format("%d %%", VolumeSlider->GetValue())); break; case ID_DPL2DECODER: SConfig::GetInstance().m_LocalCoreStartupParameter.bDPL2Decoder = DPL2Decoder->IsChecked(); break; case ID_BACKEND: VolumeSlider->Enable(SupportsVolumeChanges(WxStrToStr(BackendSelection->GetStringSelection()))); Latency->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL); DPL2Decoder->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL || WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_PULSEAUDIO); // Don't save the translated BACKEND_NULLSOUND string SConfig::GetInstance().sBackend = BackendSelection->GetSelection() ? WxStrToStr(BackendSelection->GetStringSelection()) : BACKEND_NULLSOUND; AudioCommon::UpdateSoundStream(); break; case ID_LATENCY: SConfig::GetInstance().m_LocalCoreStartupParameter.iLatency = Latency->GetValue(); break; default: break; } } void CConfigMain::AddAudioBackends() { for (const std::string& backend : AudioCommon::GetSoundBackends()) { BackendSelection->Append(wxGetTranslation(StrToWxStr(backend))); int num = BackendSelection-> FindString(StrToWxStr(SConfig::GetInstance().sBackend)); BackendSelection->SetSelection(num); } } bool CConfigMain::SupportsVolumeChanges(std::string backend) { //FIXME: this one should ask the backend whether it supports it. // but getting the backend from string etc. is probably // too much just to enable/disable a stupid slider... return (backend == BACKEND_COREAUDIO || backend == BACKEND_OPENAL || backend == BACKEND_XAUDIO2); } // GC settings // ----------------------- void CConfigMain::GCSettingsChanged(wxCommandEvent& event) { int exidevice = 0; switch (event.GetId()) { // GameCube - IPL case ID_GC_SRAM_LNG: SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage = GCSystemLang->GetSelection(); bRefreshList = true; break; // GameCube - IPL Settings case ID_GC_ALWAYS_HLE_BS2: SConfig::GetInstance().m_LocalCoreStartupParameter.bHLE_BS2 = GCAlwaysHLE_BS2->IsChecked(); break; // GameCube - Devices case ID_GC_EXIDEVICE_SP1: exidevice++; case ID_GC_EXIDEVICE_SLOTB: exidevice++; case ID_GC_EXIDEVICE_SLOTA: ChooseEXIDevice(event.GetString(), exidevice); break; case ID_GC_EXIDEVICE_SLOTA_PATH: ChooseSlotPath(true, SConfig::GetInstance().m_EXIDevice[0]); break; case ID_GC_EXIDEVICE_SLOTB_PATH: ChooseSlotPath(false, SConfig::GetInstance().m_EXIDevice[1]); break; } } void CConfigMain::ChooseSlotPath(bool isSlotA, TEXIDevices device_type) { bool memcard = (device_type == EXIDEVICE_MEMORYCARD); std::string path; std::string cardname; std::string ext; std::string pathA = SConfig::GetInstance().m_strMemoryCardA; std::string pathB = SConfig::GetInstance().m_strMemoryCardB; if (!memcard) { pathA = SConfig::GetInstance().m_strGbaCartA; pathB = SConfig::GetInstance().m_strGbaCartB; } SplitPath(isSlotA ? pathA : pathB, &path, &cardname, &ext); std::string filename = WxStrToStr(wxFileSelector( _("Choose a file to open"), StrToWxStr(path), StrToWxStr(cardname), StrToWxStr(ext), memcard ? _("GameCube Memory Cards (*.raw,*.gcp)") + "|*.raw;*.gcp" : _("Game Boy Advance Carts (*.gba)") + "|*.gba")); if (!filename.empty()) { if (File::Exists(filename)) { if (memcard) { GCMemcard memorycard(filename); if (!memorycard.IsValid()) { WxUtils::ShowErrorDialog(wxString::Format(_("Cannot use that file as a memory card.\n%s\n" \ "is not a valid GameCube memory card file"), filename.c_str())); return; } } } #ifdef _WIN32 if (!strncmp(File::GetExeDirectory().c_str(), filename.c_str(), File::GetExeDirectory().size())) { // If the Exe Directory Matches the prefix of the filename, we still need to verify // that the next character is a directory separator character, otherwise we may create an invalid path char next_char = filename.at(File::GetExeDirectory().size()) + 1; if (next_char == '/' || next_char == '\\') { filename.erase(0, File::GetExeDirectory().size() + 1); filename = "./" + filename; } } std::replace(filename.begin(), filename.end(), '\\', '/'); #endif // also check that the path isn't used for the other memcard... if (filename.compare(isSlotA ? pathB : pathA) != 0) { if (memcard) { if (isSlotA) SConfig::GetInstance().m_strMemoryCardA = filename; else SConfig::GetInstance().m_strMemoryCardB = filename; } else { if (isSlotA) SConfig::GetInstance().m_strGbaCartA = filename; else SConfig::GetInstance().m_strGbaCartB = filename; } if (Core::IsRunning()) { // Change memcard to the new file ExpansionInterface::ChangeDevice( isSlotA ? 0 : 1, // SlotA: channel 0, SlotB channel 1 device_type, 0); // SP1 is device 2, slots are device 0 } } else { WxUtils::ShowErrorDialog(_("Are you trying to use the same file in both slots?")); } } } void CConfigMain::ChooseEXIDevice(wxString deviceName, int deviceNum) { TEXIDevices tempType; if (!deviceName.compare(_(EXIDEV_MEMCARD_STR))) tempType = EXIDEVICE_MEMORYCARD; else if (!deviceName.compare(_(EXIDEV_MEMDIR_STR))) tempType = EXIDEVICE_MEMORYCARDFOLDER; else if (!deviceName.compare(_(EXIDEV_MIC_STR))) tempType = EXIDEVICE_MIC; else if (!deviceName.compare(EXIDEV_BBA_STR)) tempType = EXIDEVICE_ETH; else if (!deviceName.compare(EXIDEV_AGP_STR)) tempType = EXIDEVICE_AGP; else if (!deviceName.compare(_(EXIDEV_AM_BB_STR))) tempType = EXIDEVICE_AM_BASEBOARD; else if (!deviceName.compare(EXIDEV_GECKO_STR)) tempType = EXIDEVICE_GECKO; else if (!deviceName.compare(_(DEV_NONE_STR))) tempType = EXIDEVICE_NONE; else tempType = EXIDEVICE_DUMMY; // Gray out the memcard path button if we're not on a memcard or AGP if (tempType == EXIDEVICE_MEMORYCARD || tempType == EXIDEVICE_AGP) GCMemcardPath[deviceNum]->Enable(); else if (deviceNum == 0 || deviceNum == 1) GCMemcardPath[deviceNum]->Disable(); SConfig::GetInstance().m_EXIDevice[deviceNum] = tempType; if (Core::IsRunning()) { // Change plugged device! :D ExpansionInterface::ChangeDevice( (deviceNum == 1) ? 1 : 0, // SlotB is on channel 1, slotA and SP1 are on 0 tempType, // The device enum to change to (deviceNum == 2) ? 2 : 0); // SP1 is device 2, slots are device 0 } } // Wii settings // ------------------- void CConfigMain::WiiSettingsChanged(wxCommandEvent& event) { switch (event.GetId()) { // Wii - SYSCONF settings case ID_WII_IPL_SSV: SConfig::GetInstance().m_SYSCONF->SetData("IPL.SSV", WiiScreenSaver->IsChecked()); break; case ID_WII_IPL_E60: SConfig::GetInstance().m_SYSCONF->SetData("IPL.E60", WiiPAL60->IsChecked()); break; case ID_WII_IPL_AR: SConfig::GetInstance().m_SYSCONF->SetData("IPL.AR", WiiAspectRatio->GetSelection()); break; case ID_WII_IPL_LNG: { int wii_system_lang = WiiSystemLang->GetSelection(); SConfig::GetInstance().m_SYSCONF->SetData("IPL.LNG", wii_system_lang); u8 country_code = GetSADRCountryCode(wii_system_lang); if (!SConfig::GetInstance().m_SYSCONF->SetArrayData("IPL.SADR", &country_code, 1)) { WxUtils::ShowErrorDialog(_("Failed to update country code in SYSCONF")); } break; } // Wii - Devices case ID_WII_SD_CARD: SConfig::GetInstance().m_WiiSDCard = WiiSDCard->IsChecked(); WII_IPC_HLE_Interface::SDIO_EventNotify(); break; case ID_WII_KEYBOARD: SConfig::GetInstance().m_WiiKeyboard = WiiKeyboard->IsChecked(); break; } } // Paths settings // ------------------- void CConfigMain::ISOPathsSelectionChanged(wxCommandEvent& WXUNUSED(event)) { RemoveISOPath->Enable(ISOPaths->GetSelection() != wxNOT_FOUND); } void CConfigMain::AddRemoveISOPaths(wxCommandEvent& event) { if (event.GetId() == ID_ADDISOPATH) { wxDirDialog dialog(this, _("Choose a directory to add"), wxGetHomeDir(), wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST); if (dialog.ShowModal() == wxID_OK) { if (ISOPaths->FindString(dialog.GetPath()) != -1) { WxUtils::ShowErrorDialog(_("The chosen directory is already in the list.")); } else { bRefreshList = true; ISOPaths->Append(dialog.GetPath()); } } } else { bRefreshList = true; ISOPaths->Delete(ISOPaths->GetSelection()); // This seems to not be activated on Windows when it should be. wxw bug? #ifdef _WIN32 ISOPathsSelectionChanged(wxCommandEvent()); #endif } // Save changes right away SConfig::GetInstance().m_ISOFolder.clear(); for (unsigned int i = 0; i < ISOPaths->GetCount(); i++) SConfig::GetInstance().m_ISOFolder.push_back(WxStrToStr(ISOPaths->GetStrings()[i])); } void CConfigMain::RecursiveDirectoryChanged(wxCommandEvent& WXUNUSED(event)) { SConfig::GetInstance().m_RecursiveISOFolder = RecursiveISOPath->IsChecked(); bRefreshList = true; } void CConfigMain::DefaultISOChanged(wxFileDirPickerEvent& WXUNUSED(event)) { SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultISO = WxStrToStr(DefaultISO->GetPath()); } void CConfigMain::DVDRootChanged(wxFileDirPickerEvent& WXUNUSED(event)) { SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDVDRoot = WxStrToStr(DVDRoot->GetPath()); } void CConfigMain::ApploaderPathChanged(wxFileDirPickerEvent& WXUNUSED(event)) { SConfig::GetInstance().m_LocalCoreStartupParameter.m_strApploader = WxStrToStr(ApploaderPath->GetPath()); } void CConfigMain::NANDRootChanged(wxFileDirPickerEvent& WXUNUSED(event)) { std::string NANDPath = SConfig::GetInstance().m_NANDPath = WxStrToStr(NANDRoot->GetPath()); File::SetUserPath(D_WIIROOT_IDX, NANDPath); NANDRoot->SetPath(StrToWxStr(NANDPath)); SConfig::GetInstance().m_SYSCONF->UpdateLocation(); DiscIO::cUIDsys::AccessInstance().UpdateLocation(); DiscIO::CSharedContent::AccessInstance().UpdateLocation(); main_frame->UpdateWiiMenuChoice(); } // GFX backend selection void CConfigMain::OnSelectionChanged(wxCommandEvent& ev) { g_video_backend = g_available_video_backends[ev.GetInt()]; SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoBackend = g_video_backend->GetName(); } void CConfigMain::OnConfig(wxCommandEvent&) { if (g_video_backend) g_video_backend->ShowConfig(this); } // Change from IPL.LNG value to IPL.SADR country code inline u8 CConfigMain::GetSADRCountryCode(int language) { //http://wiibrew.org/wiki/Country_Codes u8 country_code = language; switch (country_code) { case 0: //Japanese country_code = 1; //Japan break; case 1: //English country_code = 49; //USA break; case 2: //German country_code = 78; //Germany break; case 3: //French country_code = 77; //France break; case 4: //Spanish country_code = 105; //Spain break; case 5: //Italian country_code = 83; //Italy break; case 6: //Dutch country_code = 94; //Netherlands break; case 7: //Simplified Chinese case 8: //Traditional Chinese country_code = 157; //China break; case 9: //Korean country_code = 136; //Korea break; } return country_code; }