dolphin/Source/Core/Core/ConfigManager.cpp

1101 lines
36 KiB
C++
Raw Normal View History

// Copyright 2008 Dolphin Emulator Project
2015-05-18 01:08:10 +02:00
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/ConfigManager.h"
#include <cinttypes>
2016-08-14 19:54:01 +00:00
#include <climits>
#include <memory>
#include <optional>
#include <sstream>
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
#include <variant>
#include "AudioCommon/AudioCommon.h"
#include "Common/Assert.h"
#include "Common/CDUtils.h"
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
2017-05-13 22:29:55 +01:00
#include "Common/Config/Config.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Common/NandPaths.h"
#include "Common/StringUtil.h"
#include "Common/scmrev.h"
#include "Core/Analytics.h"
#include "Core/Boot/Boot.h"
#include "Core/CommonTitles.h"
#include "Core/Config/SYSCONFSettings.h"
#include "Core/ConfigLoaders/GameConfigLoader.h"
#include "Core/Core.h"
#include "Core/FifoPlayer/FifoDataFile.h"
#include "Core/HLE/HLE.h"
2017-03-24 19:17:52 +01:00
#include "Core/HW/DVD/DVDInterface.h"
#include "Core/HW/SI/SI.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/TitleDatabase.h"
#include "VideoCommon/HiresTextures.h"
#include "DiscIO/Enums.h"
#include "DiscIO/Volume.h"
Drop the direct WAD launch hack This removes the hack that enables directly booting from WADs without installing them first for the following reasons: 1. It makes the NAND content handling much more complicated than what it should be and makes future changes like permissions or booting NAND titles without a WAD more annoying to implement. Because of this hack, we needed an extra level of abstraction (NANDContent*) which has to read tons of things from the NAND, even most of the time it's useless. This in turn forces us to have caching, which is known to break titles and requires manual cache invalidations. Annoying and error prone. 2. It prevents the WAD boot code from being easily accurate. With this change, we can simply reuse the existing launch code, and ask IOS to launch the title from the NAND. 3. The hack did not work that well since it did not cover a lot of ES commands. And it works even less since the ES accuracy fixes. This results in Dolphin returning inconsistent results: a lot of the ES "DI" commands will just fail because the active title is not installed on the NAND. uid.sys is not changed, etc. And I'm not even talking about FS stuff -- where this would still totally fail, unless we add even more unnecessary hacks. This is not just theoretical -- the system menu and the Wii Shop are known to behave strangely because the hack damages the NAND structure, and we've already had several users report issues. This commit makes it so WADs are always installed prior to launching. A future commit will remove any code that was there only for the hack.
2017-10-01 15:14:53 +02:00
#include "DiscIO/WiiWad.h"
SConfig* SConfig::m_Instance;
SConfig::SConfig()
{
LoadDefaults();
// Make sure we have log manager
LoadSettings();
}
void SConfig::Init()
{
m_Instance = new SConfig;
}
void SConfig::Shutdown()
{
delete m_Instance;
m_Instance = nullptr;
}
SConfig::~SConfig()
{
SaveSettings();
}
void SConfig::SaveSettings()
{
NOTICE_LOG(BOOT, "Saving settings to %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str());
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); // load first to not kill unknown stuff
SaveGeneralSettings(ini);
SaveInterfaceSettings(ini);
SaveDisplaySettings(ini);
SaveGameListSettings(ini);
SaveCoreSettings(ini);
SaveMovieSettings(ini);
SaveDSPSettings(ini);
SaveInputSettings(ini);
SaveFifoPlayerSettings(ini);
SaveAnalyticsSettings(ini);
2015-06-16 21:48:09 +02:00
SaveNetworkSettings(ini);
SaveBluetoothPassthroughSettings(ini);
SaveUSBPassthroughSettings(ini);
SaveAutoUpdateSettings(ini);
2014-06-16 01:12:43 -04:00
ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX));
2017-05-13 22:29:55 +01:00
Config::Save();
2014-06-16 01:12:43 -04:00
}
2016-06-25 11:24:43 -04:00
namespace
{
void CreateDumpPath(const std::string& path)
{
if (path.empty())
return;
File::SetUserPath(D_DUMP_IDX, path + '/');
File::CreateFullPath(File::GetUserPath(D_DUMPAUDIO_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPDSP_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPSSL_IDX));
2016-06-25 11:24:43 -04:00
File::CreateFullPath(File::GetUserPath(D_DUMPFRAMES_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPTEXTURES_IDX));
}
} // namespace
2014-06-16 01:12:43 -04:00
void SConfig::SaveGeneralSettings(IniFile& ini)
{
IniFile::Section* general = ini.GetOrCreateSection("General");
// General
general->Set("ShowLag", m_ShowLag);
general->Set("ShowFrameCount", m_ShowFrameCount);
// ISO folders
// Clear removed folders
int oldPaths;
int numPaths = (int)m_ISOFolder.size();
general->Get("ISOPaths", &oldPaths, 0);
for (int i = numPaths; i < oldPaths; i++)
{
ini.DeleteKey("General", StringFromFormat("ISOPath%i", i));
}
general->Set("ISOPaths", numPaths);
for (int i = 0; i < numPaths; i++)
{
general->Set(StringFromFormat("ISOPath%i", i), m_ISOFolder[i]);
}
general->Set("RecursiveISOPaths", m_RecursiveISOFolder);
general->Set("NANDRootPath", m_NANDPath);
2016-06-25 11:24:43 -04:00
general->Set("DumpPath", m_DumpPath);
CreateDumpPath(m_DumpPath);
general->Set("WirelessMac", m_WirelessMac);
general->Set("WiiSDCardPath", m_strWiiSDCardPath);
2014-06-16 01:12:43 -04:00
#ifdef USE_GDBSTUB
#ifndef _WIN32
general->Set("GDBSocket", gdb_socket);
#endif
general->Set("GDBPort", iGDBPort);
2014-06-16 01:12:43 -04:00
#endif
}
void SConfig::SaveInterfaceSettings(IniFile& ini)
{
IniFile::Section* interface = ini.GetOrCreateSection("Interface");
interface->Set("ConfirmStop", bConfirmStop);
interface->Set("UsePanicHandlers", bUsePanicHandlers);
interface->Set("OnScreenDisplayMessages", bOnScreenDisplayMessages);
interface->Set("HideCursor", bHideCursor);
2016-08-14 19:54:01 +00:00
interface->Set("MainWindowPosX", iPosX);
interface->Set("MainWindowPosY", iPosY);
interface->Set("MainWindowWidth", iWidth);
interface->Set("MainWindowHeight", iHeight);
interface->Set("LanguageCode", m_InterfaceLanguage);
interface->Set("ShowToolbar", m_InterfaceToolbar);
interface->Set("ShowStatusbar", m_InterfaceStatusbar);
interface->Set("ShowLogWindow", m_InterfaceLogWindow);
interface->Set("ShowLogConfigWindow", m_InterfaceLogConfigWindow);
interface->Set("ExtendedFPSInfo", m_InterfaceExtendedFPSInfo);
interface->Set("ShowActiveTitle", m_show_active_title);
interface->Set("UseBuiltinTitleDatabase", m_use_builtin_title_database);
interface->Set("ThemeName", theme_name);
interface->Set("PauseOnFocusLost", m_PauseOnFocusLost);
interface->Set("DisableTooltips", m_DisableTooltips);
interface->Set("DebugModeEnabled", bEnableDebugging);
2014-06-16 01:12:43 -04:00
}
void SConfig::SaveDisplaySettings(IniFile& ini)
{
IniFile::Section* display = ini.GetOrCreateSection("Display");
2014-06-16 01:12:43 -04:00
2017-11-17 12:55:43 -08:00
display->Set("FullscreenDisplayRes", strFullscreenResolution);
display->Set("Fullscreen", bFullscreen);
display->Set("RenderToMain", bRenderToMain);
display->Set("RenderWindowXPos", iRenderWindowXPos);
display->Set("RenderWindowYPos", iRenderWindowYPos);
display->Set("RenderWindowWidth", iRenderWindowWidth);
display->Set("RenderWindowHeight", iRenderWindowHeight);
display->Set("RenderWindowAutoSize", bRenderWindowAutoSize);
display->Set("KeepWindowOnTop", bKeepWindowOnTop);
display->Set("DisableScreenSaver", bDisableScreenSaver);
2014-06-16 01:12:43 -04:00
}
void SConfig::SaveGameListSettings(IniFile& ini)
{
IniFile::Section* gamelist = ini.GetOrCreateSection("GameList");
gamelist->Set("ListDrives", m_ListDrives);
gamelist->Set("ListWad", m_ListWad);
gamelist->Set("ListElfDol", m_ListElfDol);
gamelist->Set("ListWii", m_ListWii);
gamelist->Set("ListGC", m_ListGC);
gamelist->Set("ListJap", m_ListJap);
gamelist->Set("ListPal", m_ListPal);
gamelist->Set("ListUsa", m_ListUsa);
gamelist->Set("ListAustralia", m_ListAustralia);
gamelist->Set("ListFrance", m_ListFrance);
gamelist->Set("ListGermany", m_ListGermany);
gamelist->Set("ListItaly", m_ListItaly);
gamelist->Set("ListKorea", m_ListKorea);
gamelist->Set("ListNetherlands", m_ListNetherlands);
gamelist->Set("ListRussia", m_ListRussia);
gamelist->Set("ListSpain", m_ListSpain);
gamelist->Set("ListTaiwan", m_ListTaiwan);
gamelist->Set("ListWorld", m_ListWorld);
gamelist->Set("ListUnknown", m_ListUnknown);
gamelist->Set("ListSort", m_ListSort);
gamelist->Set("ListSortSecondary", m_ListSort2);
gamelist->Set("ColumnPlatform", m_showSystemColumn);
gamelist->Set("ColumnBanner", m_showBannerColumn);
2017-05-08 19:03:59 +02:00
gamelist->Set("ColumnDescription", m_showDescriptionColumn);
gamelist->Set("ColumnTitle", m_showTitleColumn);
gamelist->Set("ColumnNotes", m_showMakerColumn);
gamelist->Set("ColumnFileName", m_showFileNameColumn);
gamelist->Set("ColumnID", m_showIDColumn);
gamelist->Set("ColumnRegion", m_showRegionColumn);
gamelist->Set("ColumnSize", m_showSizeColumn);
2014-06-16 01:12:43 -04:00
}
void SConfig::SaveCoreSettings(IniFile& ini)
{
IniFile::Section* core = ini.GetOrCreateSection("Core");
core->Set("SkipIPL", bHLE_BS2);
core->Set("TimingVariance", iTimingVariance);
core->Set("CPUCore", iCPUCore);
core->Set("Fastmem", bFastmem);
core->Set("CPUThread", bCPUThread);
core->Set("DSPHLE", bDSPHLE);
core->Set("SyncOnSkipIdle", bSyncGPUOnSkipIdleHack);
core->Set("SyncGPU", bSyncGPU);
core->Set("SyncGpuMaxDistance", iSyncGpuMaxDistance);
core->Set("SyncGpuMinDistance", iSyncGpuMinDistance);
core->Set("SyncGpuOverclock", fSyncGpuOverclock);
core->Set("FPRF", bFPRF);
core->Set("AccurateNaNs", bAccurateNaNs);
core->Set("DefaultISO", m_strDefaultISO);
core->Set("EnableCheats", bEnableCheats);
core->Set("SelectedLanguage", SelectedLanguage);
core->Set("OverrideGCLang", bOverrideGCLanguage);
core->Set("DPL2Decoder", bDPL2Decoder);
core->Set("AudioLatency", iLatency);
core->Set("AudioStretch", m_audio_stretch);
core->Set("AudioStretchMaxLatency", m_audio_stretch_max_latency);
core->Set("MemcardAPath", m_strMemoryCardA);
core->Set("MemcardBPath", m_strMemoryCardB);
core->Set("AgpCartAPath", m_strGbaCartA);
core->Set("AgpCartBPath", m_strGbaCartB);
core->Set("SlotA", m_EXIDevice[0]);
core->Set("SlotB", m_EXIDevice[1]);
core->Set("SerialPort1", m_EXIDevice[2]);
core->Set("BBA_MAC", m_bba_mac);
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
{
core->Set(StringFromFormat("SIDevice%i", i), m_SIDevice[i]);
core->Set(StringFromFormat("AdapterRumble%i", i), m_AdapterRumble[i]);
core->Set(StringFromFormat("SimulateKonga%i", i), m_AdapterKonga[i]);
}
core->Set("WiiSDCard", m_WiiSDCard);
core->Set("WiiKeyboard", m_WiiKeyboard);
core->Set("WiimoteContinuousScanning", m_WiimoteContinuousScanning);
core->Set("WiimoteEnableSpeaker", m_WiimoteEnableSpeaker);
core->Set("RunCompareServer", bRunCompareServer);
core->Set("RunCompareClient", bRunCompareClient);
core->Set("EmulationSpeed", m_EmulationSpeed);
core->Set("FrameSkip", m_FrameSkip);
core->Set("Overclock", m_OCFactor);
core->Set("OverclockEnable", m_OCEnable);
core->Set("GFXBackend", m_strVideoBackend);
core->Set("GPUDeterminismMode", m_strGPUDeterminismMode);
core->Set("PerfMapDir", m_perfDir);
2016-07-13 16:46:14 -04:00
core->Set("EnableCustomRTC", bEnableCustomRTC);
core->Set("CustomRTCValue", m_customRTCValue);
core->Set("EnableSignatureChecks", m_enable_signature_checks);
2014-06-16 01:12:43 -04:00
}
2014-06-16 01:12:43 -04:00
void SConfig::SaveMovieSettings(IniFile& ini)
{
IniFile::Section* movie = ini.GetOrCreateSection("Movie");
2014-06-16 01:12:43 -04:00
movie->Set("PauseMovie", m_PauseMovie);
movie->Set("Author", m_strMovieAuthor);
movie->Set("DumpFrames", m_DumpFrames);
movie->Set("DumpFramesSilent", m_DumpFramesSilent);
movie->Set("ShowInputDisplay", m_ShowInputDisplay);
2016-07-19 20:23:25 -04:00
movie->Set("ShowRTC", m_ShowRTC);
}
2014-06-16 01:12:43 -04:00
void SConfig::SaveDSPSettings(IniFile& ini)
{
IniFile::Section* dsp = ini.GetOrCreateSection("DSP");
2014-06-16 01:12:43 -04:00
dsp->Set("EnableJIT", m_DSPEnableJIT);
dsp->Set("DumpAudio", m_DumpAudio);
2017-01-08 13:51:00 -05:00
dsp->Set("DumpAudioSilent", m_DumpAudioSilent);
dsp->Set("DumpUCode", m_DumpUCode);
dsp->Set("Backend", sBackend);
dsp->Set("Volume", m_Volume);
dsp->Set("CaptureLog", m_DSPCaptureLog);
2014-06-16 01:12:43 -04:00
}
void SConfig::SaveInputSettings(IniFile& ini)
{
IniFile::Section* input = ini.GetOrCreateSection("Input");
input->Set("BackgroundInput", m_BackgroundInput);
}
2014-06-16 01:12:43 -04:00
void SConfig::SaveFifoPlayerSettings(IniFile& ini)
{
IniFile::Section* fifoplayer = ini.GetOrCreateSection("FifoPlayer");
2014-06-16 01:12:43 -04:00
fifoplayer->Set("LoopReplay", bLoopFifoReplay);
2014-06-16 01:12:43 -04:00
}
2015-06-16 21:48:09 +02:00
void SConfig::SaveNetworkSettings(IniFile& ini)
{
IniFile::Section* network = ini.GetOrCreateSection("Network");
network->Set("SSLDumpRead", m_SSLDumpRead);
network->Set("SSLDumpWrite", m_SSLDumpWrite);
network->Set("SSLVerifyCertificates", m_SSLVerifyCert);
network->Set("SSLDumpRootCA", m_SSLDumpRootCA);
network->Set("SSLDumpPeerCert", m_SSLDumpPeerCert);
2015-06-16 21:48:09 +02:00
}
void SConfig::SaveAnalyticsSettings(IniFile& ini)
{
IniFile::Section* analytics = ini.GetOrCreateSection("Analytics");
analytics->Set("ID", m_analytics_id);
analytics->Set("Enabled", m_analytics_enabled);
analytics->Set("PermissionAsked", m_analytics_permission_asked);
}
void SConfig::SaveBluetoothPassthroughSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("BluetoothPassthrough");
section->Set("Enabled", m_bt_passthrough_enabled);
section->Set("VID", m_bt_passthrough_vid);
section->Set("PID", m_bt_passthrough_pid);
section->Set("LinkKeys", m_bt_passthrough_link_keys);
}
void SConfig::SaveUSBPassthroughSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("USBPassthrough");
std::ostringstream oss;
for (const auto& device : m_usb_passthrough_devices)
oss << StringFromFormat("%04x:%04x", device.first, device.second) << ',';
std::string devices_string = oss.str();
if (!devices_string.empty())
devices_string.pop_back();
section->Set("Devices", devices_string);
}
void SConfig::SaveAutoUpdateSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("AutoUpdate");
section->Set("UpdateTrack", m_auto_update_track);
section->Set("HashOverride", m_auto_update_hash_override);
}
void SConfig::LoadSettings()
{
2017-05-13 22:29:55 +01:00
Config::Load();
INFO_LOG(BOOT, "Loading Settings from %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str());
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
LoadGeneralSettings(ini);
LoadInterfaceSettings(ini);
LoadDisplaySettings(ini);
LoadGameListSettings(ini);
LoadCoreSettings(ini);
LoadMovieSettings(ini);
LoadDSPSettings(ini);
LoadInputSettings(ini);
LoadFifoPlayerSettings(ini);
2015-06-16 21:48:09 +02:00
LoadNetworkSettings(ini);
LoadAnalyticsSettings(ini);
LoadBluetoothPassthroughSettings(ini);
LoadUSBPassthroughSettings(ini);
LoadAutoUpdateSettings(ini);
2014-06-16 01:12:43 -04:00
}
2014-06-16 01:12:43 -04:00
void SConfig::LoadGeneralSettings(IniFile& ini)
{
IniFile::Section* general = ini.GetOrCreateSection("General");
general->Get("ShowLag", &m_ShowLag, false);
general->Get("ShowFrameCount", &m_ShowFrameCount, false);
2014-06-16 01:12:43 -04:00
#ifdef USE_GDBSTUB
#ifndef _WIN32
general->Get("GDBSocket", &gdb_socket, "");
#endif
general->Get("GDBPort", &(iGDBPort), -1);
2014-06-16 01:12:43 -04:00
#endif
m_ISOFolder.clear();
int numISOPaths;
if (general->Get("ISOPaths", &numISOPaths, 0))
{
for (int i = 0; i < numISOPaths; i++)
{
std::string tmpPath;
general->Get(StringFromFormat("ISOPath%i", i), &tmpPath, "");
m_ISOFolder.push_back(std::move(tmpPath));
}
}
general->Get("RecursiveISOPaths", &m_RecursiveISOFolder, false);
general->Get("NANDRootPath", &m_NANDPath);
File::SetUserPath(D_WIIROOT_IDX, m_NANDPath);
2016-06-25 11:24:43 -04:00
general->Get("DumpPath", &m_DumpPath);
CreateDumpPath(m_DumpPath);
general->Get("WirelessMac", &m_WirelessMac);
general->Get("WiiSDCardPath", &m_strWiiSDCardPath, File::GetUserPath(F_WIISDCARD_IDX));
File::SetUserPath(F_WIISDCARD_IDX, m_strWiiSDCardPath);
2014-06-16 01:12:43 -04:00
}
void SConfig::LoadInterfaceSettings(IniFile& ini)
{
IniFile::Section* interface = ini.GetOrCreateSection("Interface");
interface->Get("ConfirmStop", &bConfirmStop, true);
interface->Get("UsePanicHandlers", &bUsePanicHandlers, true);
interface->Get("OnScreenDisplayMessages", &bOnScreenDisplayMessages, true);
interface->Get("HideCursor", &bHideCursor, false);
2016-08-14 19:54:01 +00:00
interface->Get("MainWindowPosX", &iPosX, INT_MIN);
interface->Get("MainWindowPosY", &iPosY, INT_MIN);
interface->Get("MainWindowWidth", &iWidth, -1);
interface->Get("MainWindowHeight", &iHeight, -1);
interface->Get("LanguageCode", &m_InterfaceLanguage, "");
interface->Get("ShowToolbar", &m_InterfaceToolbar, true);
interface->Get("ShowStatusbar", &m_InterfaceStatusbar, true);
interface->Get("ShowLogWindow", &m_InterfaceLogWindow, false);
interface->Get("ShowLogConfigWindow", &m_InterfaceLogConfigWindow, false);
interface->Get("ExtendedFPSInfo", &m_InterfaceExtendedFPSInfo, false);
interface->Get("ShowActiveTitle", &m_show_active_title, true);
interface->Get("UseBuiltinTitleDatabase", &m_use_builtin_title_database, true);
interface->Get("ThemeName", &theme_name, DEFAULT_THEME_DIR);
interface->Get("PauseOnFocusLost", &m_PauseOnFocusLost, false);
interface->Get("DisableTooltips", &m_DisableTooltips, false);
interface->Get("DebugModeEnabled", &bEnableDebugging, false);
2014-06-16 01:12:43 -04:00
}
void SConfig::LoadDisplaySettings(IniFile& ini)
{
IniFile::Section* display = ini.GetOrCreateSection("Display");
2014-06-16 01:12:43 -04:00
display->Get("Fullscreen", &bFullscreen, false);
2017-11-17 12:55:43 -08:00
display->Get("FullscreenDisplayRes", &strFullscreenResolution, "Auto");
display->Get("RenderToMain", &bRenderToMain, false);
display->Get("RenderWindowXPos", &iRenderWindowXPos, -1);
display->Get("RenderWindowYPos", &iRenderWindowYPos, -1);
display->Get("RenderWindowWidth", &iRenderWindowWidth, 640);
display->Get("RenderWindowHeight", &iRenderWindowHeight, 480);
display->Get("RenderWindowAutoSize", &bRenderWindowAutoSize, false);
display->Get("KeepWindowOnTop", &bKeepWindowOnTop, false);
display->Get("DisableScreenSaver", &bDisableScreenSaver, true);
2014-06-16 01:12:43 -04:00
}
void SConfig::LoadGameListSettings(IniFile& ini)
{
IniFile::Section* gamelist = ini.GetOrCreateSection("GameList");
gamelist->Get("ListDrives", &m_ListDrives, false);
gamelist->Get("ListWad", &m_ListWad, true);
gamelist->Get("ListElfDol", &m_ListElfDol, true);
gamelist->Get("ListWii", &m_ListWii, true);
gamelist->Get("ListGC", &m_ListGC, true);
gamelist->Get("ListJap", &m_ListJap, true);
gamelist->Get("ListPal", &m_ListPal, true);
gamelist->Get("ListUsa", &m_ListUsa, true);
gamelist->Get("ListAustralia", &m_ListAustralia, true);
gamelist->Get("ListFrance", &m_ListFrance, true);
gamelist->Get("ListGermany", &m_ListGermany, true);
gamelist->Get("ListItaly", &m_ListItaly, true);
gamelist->Get("ListKorea", &m_ListKorea, true);
gamelist->Get("ListNetherlands", &m_ListNetherlands, true);
gamelist->Get("ListRussia", &m_ListRussia, true);
gamelist->Get("ListSpain", &m_ListSpain, true);
gamelist->Get("ListTaiwan", &m_ListTaiwan, true);
gamelist->Get("ListWorld", &m_ListWorld, true);
gamelist->Get("ListUnknown", &m_ListUnknown, true);
gamelist->Get("ListSort", &m_ListSort, 3);
gamelist->Get("ListSortSecondary", &m_ListSort2, 0);
// Gamelist columns toggles
gamelist->Get("ColumnPlatform", &m_showSystemColumn, true);
2017-05-08 19:03:59 +02:00
gamelist->Get("ColumnDescription", &m_showDescriptionColumn, false);
gamelist->Get("ColumnBanner", &m_showBannerColumn, true);
gamelist->Get("ColumnTitle", &m_showTitleColumn, true);
gamelist->Get("ColumnNotes", &m_showMakerColumn, true);
gamelist->Get("ColumnFileName", &m_showFileNameColumn, false);
gamelist->Get("ColumnID", &m_showIDColumn, false);
gamelist->Get("ColumnRegion", &m_showRegionColumn, true);
gamelist->Get("ColumnSize", &m_showSizeColumn, true);
2014-06-16 01:12:43 -04:00
}
void SConfig::LoadCoreSettings(IniFile& ini)
{
IniFile::Section* core = ini.GetOrCreateSection("Core");
core->Get("SkipIPL", &bHLE_BS2, true);
#ifdef _M_X86
core->Get("CPUCore", &iCPUCore, PowerPC::CORE_JIT64);
#elif _M_ARM_64
core->Get("CPUCore", &iCPUCore, PowerPC::CORE_JITARM64);
#else
core->Get("CPUCore", &iCPUCore, PowerPC::CORE_INTERPRETER);
#endif
core->Get("Fastmem", &bFastmem, true);
core->Get("DSPHLE", &bDSPHLE, true);
core->Get("TimingVariance", &iTimingVariance, 40);
core->Get("CPUThread", &bCPUThread, true);
core->Get("SyncOnSkipIdle", &bSyncGPUOnSkipIdleHack, true);
core->Get("DefaultISO", &m_strDefaultISO);
core->Get("EnableCheats", &bEnableCheats, false);
core->Get("SelectedLanguage", &SelectedLanguage, 0);
core->Get("OverrideGCLang", &bOverrideGCLanguage, false);
core->Get("DPL2Decoder", &bDPL2Decoder, false);
core->Get("AudioLatency", &iLatency, 20);
core->Get("AudioStretch", &m_audio_stretch, false);
core->Get("AudioStretchMaxLatency", &m_audio_stretch_max_latency, 80);
core->Get("MemcardAPath", &m_strMemoryCardA);
core->Get("MemcardBPath", &m_strMemoryCardB);
core->Get("AgpCartAPath", &m_strGbaCartA);
core->Get("AgpCartBPath", &m_strGbaCartB);
core->Get("SlotA", (int*)&m_EXIDevice[0], ExpansionInterface::EXIDEVICE_MEMORYCARDFOLDER);
2017-03-18 17:46:05 -04:00
core->Get("SlotB", (int*)&m_EXIDevice[1], ExpansionInterface::EXIDEVICE_NONE);
core->Get("SerialPort1", (int*)&m_EXIDevice[2], ExpansionInterface::EXIDEVICE_NONE);
core->Get("BBA_MAC", &m_bba_mac);
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
{
core->Get(StringFromFormat("SIDevice%i", i), (u32*)&m_SIDevice[i],
(i == 0) ? SerialInterface::SIDEVICE_GC_CONTROLLER : SerialInterface::SIDEVICE_NONE);
core->Get(StringFromFormat("AdapterRumble%i", i), &m_AdapterRumble[i], true);
core->Get(StringFromFormat("SimulateKonga%i", i), &m_AdapterKonga[i], false);
}
core->Get("WiiSDCard", &m_WiiSDCard, false);
core->Get("WiiKeyboard", &m_WiiKeyboard, false);
core->Get("WiimoteContinuousScanning", &m_WiimoteContinuousScanning, false);
core->Get("WiimoteEnableSpeaker", &m_WiimoteEnableSpeaker, false);
core->Get("RunCompareServer", &bRunCompareServer, false);
core->Get("RunCompareClient", &bRunCompareClient, false);
core->Get("MMU", &bMMU, bMMU);
core->Get("BBDumpPort", &iBBDumpPort, -1);
core->Get("SyncGPU", &bSyncGPU, false);
core->Get("SyncGpuMaxDistance", &iSyncGpuMaxDistance, 200000);
core->Get("SyncGpuMinDistance", &iSyncGpuMinDistance, -200000);
core->Get("SyncGpuOverclock", &fSyncGpuOverclock, 1.0f);
core->Get("FastDiscSpeed", &bFastDiscSpeed, false);
core->Get("DCBZ", &bDCBZOFF, false);
core->Get("LowDCBZHack", &bLowDCBZHack, false);
core->Get("FPRF", &bFPRF, false);
core->Get("AccurateNaNs", &bAccurateNaNs, false);
core->Get("EmulationSpeed", &m_EmulationSpeed, 1.0f);
core->Get("Overclock", &m_OCFactor, 1.0f);
core->Get("OverclockEnable", &m_OCEnable, false);
core->Get("FrameSkip", &m_FrameSkip, 0);
core->Get("GFXBackend", &m_strVideoBackend, "");
core->Get("GPUDeterminismMode", &m_strGPUDeterminismMode, "auto");
core->Get("PerfMapDir", &m_perfDir, "");
2016-07-13 16:46:14 -04:00
core->Get("EnableCustomRTC", &bEnableCustomRTC, false);
// Default to seconds between 1.1.1970 and 1.1.2000
core->Get("CustomRTCValue", &m_customRTCValue, 946684800);
core->Get("EnableSignatureChecks", &m_enable_signature_checks, true);
2014-06-16 01:12:43 -04:00
}
2014-06-16 01:12:43 -04:00
void SConfig::LoadMovieSettings(IniFile& ini)
{
IniFile::Section* movie = ini.GetOrCreateSection("Movie");
2014-06-16 01:12:43 -04:00
movie->Get("PauseMovie", &m_PauseMovie, false);
movie->Get("Author", &m_strMovieAuthor, "");
movie->Get("DumpFrames", &m_DumpFrames, false);
movie->Get("DumpFramesSilent", &m_DumpFramesSilent, false);
movie->Get("ShowInputDisplay", &m_ShowInputDisplay, false);
2016-07-19 20:23:25 -04:00
movie->Get("ShowRTC", &m_ShowRTC, false);
2014-06-16 01:12:43 -04:00
}
void SConfig::LoadDSPSettings(IniFile& ini)
{
IniFile::Section* dsp = ini.GetOrCreateSection("DSP");
2014-06-16 01:12:43 -04:00
dsp->Get("EnableJIT", &m_DSPEnableJIT, true);
dsp->Get("DumpAudio", &m_DumpAudio, false);
2017-01-08 13:51:00 -05:00
dsp->Get("DumpAudioSilent", &m_DumpAudioSilent, false);
dsp->Get("DumpUCode", &m_DumpUCode, false);
dsp->Get("Backend", &sBackend, AudioCommon::GetDefaultSoundBackend());
dsp->Get("Volume", &m_Volume, 100);
dsp->Get("CaptureLog", &m_DSPCaptureLog, false);
m_IsMuted = false;
2014-06-16 01:12:43 -04:00
}
void SConfig::LoadInputSettings(IniFile& ini)
{
IniFile::Section* input = ini.GetOrCreateSection("Input");
input->Get("BackgroundInput", &m_BackgroundInput, false);
}
2014-06-16 01:12:43 -04:00
void SConfig::LoadFifoPlayerSettings(IniFile& ini)
{
IniFile::Section* fifoplayer = ini.GetOrCreateSection("FifoPlayer");
2014-06-16 01:12:43 -04:00
fifoplayer->Get("LoopReplay", &bLoopFifoReplay, true);
}
2015-06-16 21:48:09 +02:00
void SConfig::LoadNetworkSettings(IniFile& ini)
{
IniFile::Section* network = ini.GetOrCreateSection("Network");
network->Get("SSLDumpRead", &m_SSLDumpRead, false);
network->Get("SSLDumpWrite", &m_SSLDumpWrite, false);
network->Get("SSLVerifyCertificates", &m_SSLVerifyCert, true);
network->Get("SSLDumpRootCA", &m_SSLDumpRootCA, false);
network->Get("SSLDumpPeerCert", &m_SSLDumpPeerCert, false);
2015-06-16 21:48:09 +02:00
}
void SConfig::LoadAnalyticsSettings(IniFile& ini)
{
IniFile::Section* analytics = ini.GetOrCreateSection("Analytics");
analytics->Get("ID", &m_analytics_id, "");
analytics->Get("Enabled", &m_analytics_enabled, false);
analytics->Get("PermissionAsked", &m_analytics_permission_asked, false);
}
void SConfig::LoadBluetoothPassthroughSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("BluetoothPassthrough");
section->Get("Enabled", &m_bt_passthrough_enabled, false);
section->Get("VID", &m_bt_passthrough_vid, -1);
section->Get("PID", &m_bt_passthrough_pid, -1);
section->Get("LinkKeys", &m_bt_passthrough_link_keys, "");
}
void SConfig::LoadUSBPassthroughSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("USBPassthrough");
m_usb_passthrough_devices.clear();
std::string devices_string;
section->Get("Devices", &devices_string, "");
for (const auto& pair : SplitString(devices_string, ','))
{
const auto index = pair.find(':');
if (index == std::string::npos)
continue;
const u16 vid = static_cast<u16>(strtol(pair.substr(0, index).c_str(), nullptr, 16));
const u16 pid = static_cast<u16>(strtol(pair.substr(index + 1).c_str(), nullptr, 16));
if (vid && pid)
m_usb_passthrough_devices.emplace(vid, pid);
}
}
void SConfig::LoadAutoUpdateSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("AutoUpdate");
section->Get("UpdateTrack", &m_auto_update_track, SCM_UPDATE_TRACK_STR);
section->Get("HashOverride", &m_auto_update_hash_override, "");
}
void SConfig::ResetRunningGameMetadata()
{
SetRunningGameMetadata("00000000", 0, 0, Core::TitleDatabase::TitleType::Other);
}
void SConfig::SetRunningGameMetadata(const DiscIO::Volume& volume,
const DiscIO::Partition& partition)
{
SetRunningGameMetadata(volume.GetGameID(partition), volume.GetTitleID(partition).value_or(0),
volume.GetRevision(partition).value_or(0),
Core::TitleDatabase::TitleType::Other);
}
void SConfig::SetRunningGameMetadata(const IOS::ES::TMDReader& tmd)
{
const u64 tmd_title_id = tmd.GetTitleId();
// If we're launching a disc game, we want to read the revision from
// the disc header instead of the TMD. They can differ.
// (IOS HLE ES calls us with a TMDReader rather than a volume when launching
// a disc game, because ES has no reason to be accessing the disc directly.)
if (!DVDInterface::UpdateRunningGameMetadata(tmd_title_id))
{
// If not launching a disc game, just read everything from the TMD.
SetRunningGameMetadata(tmd.GetGameID(), tmd_title_id, tmd.GetTitleVersion(),
Core::TitleDatabase::TitleType::Channel);
}
}
void SConfig::SetRunningGameMetadata(const std::string& game_id, u64 title_id, u16 revision,
Core::TitleDatabase::TitleType type)
{
const bool was_changed = m_game_id != game_id || m_title_id != title_id || m_revision != revision;
m_game_id = game_id;
m_title_id = title_id;
m_revision = revision;
2017-06-05 13:55:54 +02:00
if (game_id.length() == 6)
{
m_debugger_game_id = game_id;
}
else if (title_id != 0)
{
m_debugger_game_id =
StringFromFormat("%08X_%08X", static_cast<u32>(title_id >> 32), static_cast<u32>(title_id));
}
else
{
m_debugger_game_id.clear();
}
if (!was_changed)
return;
if (game_id == "00000000")
{
m_title_description.clear();
return;
}
const Core::TitleDatabase title_database;
m_title_description = title_database.Describe(m_game_id, type);
NOTICE_LOG(CORE, "Active title: %s", m_title_description.c_str());
Config::AddLayer(ConfigLoaders::GenerateGlobalGameConfigLoader(game_id, revision));
Config::AddLayer(ConfigLoaders::GenerateLocalGameConfigLoader(game_id, revision));
if (Core::IsRunning())
{
// TODO: have a callback mechanism for title changes?
g_symbolDB.Clear();
CBoot::LoadMapFromFilename();
HLE::Reload();
PatchEngine::Reload();
HiresTexture::Update();
DolphinAnalytics::Instance()->ReportGameStart();
}
}
void SConfig::LoadDefaults()
{
bEnableDebugging = false;
bAutomaticStart = false;
bBootToPause = false;
#ifdef USE_GDBSTUB
iGDBPort = -1;
#ifndef _WIN32
gdb_socket = "";
#endif
#endif
iCPUCore = PowerPC::DefaultCPUCore();
iTimingVariance = 40;
bCPUThread = false;
bSyncGPUOnSkipIdleHack = true;
bRunCompareServer = false;
bDSPHLE = true;
bFastmem = true;
bFPRF = false;
bAccurateNaNs = false;
#ifdef _M_X86_64
bMMU = true;
#else
bMMU = false;
#endif
bDCBZOFF = false;
bLowDCBZHack = false;
iBBDumpPort = -1;
bSyncGPU = false;
bFastDiscSpeed = false;
m_strWiiSDCardPath = File::GetUserPath(F_WIISDCARD_IDX);
bEnableMemcardSdWriting = true;
SelectedLanguage = 0;
bOverrideGCLanguage = false;
bWii = false;
bDPL2Decoder = false;
iLatency = 20;
m_audio_stretch = false;
m_audio_stretch_max_latency = 80;
2016-08-14 19:54:01 +00:00
iPosX = INT_MIN;
iPosY = INT_MIN;
iWidth = -1;
iHeight = -1;
m_analytics_id = "";
m_analytics_enabled = false;
m_analytics_permission_asked = false;
bLoopFifoReplay = true;
bJITOff = false; // debugger only settings
bJITLoadStoreOff = false;
bJITLoadStoreFloatingOff = false;
bJITLoadStorePairedOff = false;
bJITFloatingPointOff = false;
bJITIntegerOff = false;
bJITPairedOff = false;
bJITSystemRegistersOff = false;
bJITBranchOff = false;
ResetRunningGameMetadata();
}
2016-06-25 11:24:43 -04:00
bool SConfig::IsUSBDeviceWhitelisted(const std::pair<u16, u16> vid_pid) const
{
return m_usb_passthrough_devices.find(vid_pid) != m_usb_passthrough_devices.end();
}
// The reason we need this function is because some memory card code
// expects to get a non-NTSC-K region even if we're emulating an NTSC-K Wii.
DiscIO::Region SConfig::ToGameCubeRegion(DiscIO::Region region)
{
if (region != DiscIO::Region::NTSC_K)
return region;
// GameCube has no NTSC-K region. No choice of replacement value is completely
// non-arbitrary, but let's go with NTSC-J since Korean GameCubes are NTSC-J.
return DiscIO::Region::NTSC_J;
}
const char* SConfig::GetDirectoryForRegion(DiscIO::Region region)
{
switch (region)
{
case DiscIO::Region::NTSC_J:
return JAP_DIR;
case DiscIO::Region::NTSC_U:
return USA_DIR;
case DiscIO::Region::PAL:
return EUR_DIR;
case DiscIO::Region::NTSC_K:
ASSERT_MSG(BOOT, false, "NTSC-K is not a valid GameCube region");
return nullptr;
default:
return nullptr;
}
}
2017-05-21 22:21:34 +01:00
std::string SConfig::GetBootROMPath(const std::string& region_directory) const
{
const std::string path =
File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + region_directory + DIR_SEP GC_IPL;
if (!File::Exists(path))
return File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + region_directory + DIR_SEP GC_IPL;
return path;
}
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
struct SetGameMetadata
{
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
SetGameMetadata(SConfig* config_, DiscIO::Region* region_) : config(config_), region(region_) {}
bool operator()(const BootParameters::Disc& disc) const
{
config->SetRunningGameMetadata(*disc.volume, disc.volume->GetGamePartition());
config->bWii = disc.volume->GetVolumeType() == DiscIO::Platform::WiiDisc;
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
config->m_disc_booted_from_game_list = true;
*region = disc.volume->GetRegion();
return true;
}
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
bool operator()(const BootParameters::Executable& executable) const
{
if (!executable.reader->IsValid())
return false;
config->bWii = executable.reader->IsWii();
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
*region = DiscIO::Region::Unknown;
2017-06-05 13:55:54 +02:00
// Strip the .elf/.dol file extension and directories before the name
SplitPath(executable.path, nullptr, &config->m_debugger_game_id, nullptr);
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
return true;
}
Drop the direct WAD launch hack This removes the hack that enables directly booting from WADs without installing them first for the following reasons: 1. It makes the NAND content handling much more complicated than what it should be and makes future changes like permissions or booting NAND titles without a WAD more annoying to implement. Because of this hack, we needed an extra level of abstraction (NANDContent*) which has to read tons of things from the NAND, even most of the time it's useless. This in turn forces us to have caching, which is known to break titles and requires manual cache invalidations. Annoying and error prone. 2. It prevents the WAD boot code from being easily accurate. With this change, we can simply reuse the existing launch code, and ask IOS to launch the title from the NAND. 3. The hack did not work that well since it did not cover a lot of ES commands. And it works even less since the ES accuracy fixes. This results in Dolphin returning inconsistent results: a lot of the ES "DI" commands will just fail because the active title is not installed on the NAND. uid.sys is not changed, etc. And I'm not even talking about FS stuff -- where this would still totally fail, unless we add even more unnecessary hacks. This is not just theoretical -- the system menu and the Wii Shop are known to behave strangely because the hack damages the NAND structure, and we've already had several users report issues. This commit makes it so WADs are always installed prior to launching. A future commit will remove any code that was there only for the hack.
2017-10-01 15:14:53 +02:00
bool operator()(const DiscIO::WiiWAD& wad) const
{
Drop the direct WAD launch hack This removes the hack that enables directly booting from WADs without installing them first for the following reasons: 1. It makes the NAND content handling much more complicated than what it should be and makes future changes like permissions or booting NAND titles without a WAD more annoying to implement. Because of this hack, we needed an extra level of abstraction (NANDContent*) which has to read tons of things from the NAND, even most of the time it's useless. This in turn forces us to have caching, which is known to break titles and requires manual cache invalidations. Annoying and error prone. 2. It prevents the WAD boot code from being easily accurate. With this change, we can simply reuse the existing launch code, and ask IOS to launch the title from the NAND. 3. The hack did not work that well since it did not cover a lot of ES commands. And it works even less since the ES accuracy fixes. This results in Dolphin returning inconsistent results: a lot of the ES "DI" commands will just fail because the active title is not installed on the NAND. uid.sys is not changed, etc. And I'm not even talking about FS stuff -- where this would still totally fail, unless we add even more unnecessary hacks. This is not just theoretical -- the system menu and the Wii Shop are known to behave strangely because the hack damages the NAND structure, and we've already had several users report issues. This commit makes it so WADs are always installed prior to launching. A future commit will remove any code that was there only for the hack.
2017-10-01 15:14:53 +02:00
if (!wad.IsValid() || !wad.GetTMD().IsValid())
{
PanicAlertT("This WAD is not valid.");
return false;
Drop the direct WAD launch hack This removes the hack that enables directly booting from WADs without installing them first for the following reasons: 1. It makes the NAND content handling much more complicated than what it should be and makes future changes like permissions or booting NAND titles without a WAD more annoying to implement. Because of this hack, we needed an extra level of abstraction (NANDContent*) which has to read tons of things from the NAND, even most of the time it's useless. This in turn forces us to have caching, which is known to break titles and requires manual cache invalidations. Annoying and error prone. 2. It prevents the WAD boot code from being easily accurate. With this change, we can simply reuse the existing launch code, and ask IOS to launch the title from the NAND. 3. The hack did not work that well since it did not cover a lot of ES commands. And it works even less since the ES accuracy fixes. This results in Dolphin returning inconsistent results: a lot of the ES "DI" commands will just fail because the active title is not installed on the NAND. uid.sys is not changed, etc. And I'm not even talking about FS stuff -- where this would still totally fail, unless we add even more unnecessary hacks. This is not just theoretical -- the system menu and the Wii Shop are known to behave strangely because the hack damages the NAND structure, and we've already had several users report issues. This commit makes it so WADs are always installed prior to launching. A future commit will remove any code that was there only for the hack.
2017-10-01 15:14:53 +02:00
}
if (!IOS::ES::IsChannel(wad.GetTMD().GetTitleId()))
{
PanicAlertT("This WAD is not bootable.");
return false;
}
Drop the direct WAD launch hack This removes the hack that enables directly booting from WADs without installing them first for the following reasons: 1. It makes the NAND content handling much more complicated than what it should be and makes future changes like permissions or booting NAND titles without a WAD more annoying to implement. Because of this hack, we needed an extra level of abstraction (NANDContent*) which has to read tons of things from the NAND, even most of the time it's useless. This in turn forces us to have caching, which is known to break titles and requires manual cache invalidations. Annoying and error prone. 2. It prevents the WAD boot code from being easily accurate. With this change, we can simply reuse the existing launch code, and ask IOS to launch the title from the NAND. 3. The hack did not work that well since it did not cover a lot of ES commands. And it works even less since the ES accuracy fixes. This results in Dolphin returning inconsistent results: a lot of the ES "DI" commands will just fail because the active title is not installed on the NAND. uid.sys is not changed, etc. And I'm not even talking about FS stuff -- where this would still totally fail, unless we add even more unnecessary hacks. This is not just theoretical -- the system menu and the Wii Shop are known to behave strangely because the hack damages the NAND structure, and we've already had several users report issues. This commit makes it so WADs are always installed prior to launching. A future commit will remove any code that was there only for the hack.
2017-10-01 15:14:53 +02:00
const IOS::ES::TMDReader& tmd = wad.GetTMD();
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
config->SetRunningGameMetadata(tmd);
config->bWii = true;
*region = tmd.GetRegion();
return true;
}
bool operator()(const BootParameters::NANDTitle& nand_title) const
{
IOS::HLE::Kernel ios;
const IOS::ES::TMDReader tmd = ios.GetES()->FindInstalledTMD(nand_title.id);
if (!tmd.IsValid() || !IOS::ES::IsChannel(nand_title.id))
{
PanicAlertT("This title cannot be booted.");
return false;
}
config->SetRunningGameMetadata(tmd);
config->bWii = true;
*region = tmd.GetRegion();
return true;
}
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
bool operator()(const BootParameters::IPL& ipl) const
{
config->bWii = false;
*region = ipl.region;
return true;
}
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
bool operator()(const BootParameters::DFF& dff) const
{
std::unique_ptr<FifoDataFile> dff_file(FifoDataFile::Load(dff.dff_path, true));
if (!dff_file)
return false;
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
config->bWii = dff_file->GetIsWii();
*region = DiscIO::Region::NTSC_U;
return true;
}
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
private:
SConfig* config;
DiscIO::Region* region;
};
bool SConfig::SetPathsAndGameMetadata(const BootParameters& boot)
{
m_is_mios = false;
m_disc_booted_from_game_list = false;
if (!std::visit(SetGameMetadata(this, &m_region), boot.parameters))
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
return false;
// Fall back to the system menu region, if possible.
if (m_region == DiscIO::Region::Unknown)
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
{
IOS::HLE::Kernel ios;
const IOS::ES::TMDReader system_menu_tmd = ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU);
if (system_menu_tmd.IsValid())
m_region = system_menu_tmd.GetRegion();
}
// Fall back to PAL.
if (m_region == DiscIO::Region::Unknown)
m_region = DiscIO::Region::PAL;
Boot: Clean up the boot code * Move out boot parameters to a separate struct, which is not part of SConfig/ConfigManager because there is no reason for it to be there. * Move out file name parsing and constructing the appropriate params from paths to a separate function that does that, and only that. * For every different boot type we support, add a proper struct with only the required parameters, with descriptive names and use std::variant to only store what we need. * Clean up the bHLE_BS2 stuff which made no sense sometimes. Now instead of using bHLE_BS2 for two different things, both for storing the user config setting and as a runtime boot parameter, we simply replace the Disc boot params with BootParameters::IPL. * Const correctness so it's clear what can or cannot update the config. * Drop unused parameters and unneeded checks. * Make a few checks a lot more concise. (Looking at you, extension checks for disc images.) * Remove a mildly terrible workaround where we needed to pass an empty string in order to boot the GC IPL without any game inserted. (Not required anymore thanks to std::variant and std::optional.) The motivation for this are multiple: cleaning up and being able to add support for booting an installed NAND title. Without this change, it'd be pretty much impossible to implement that. Also, using std::visit with std::variant makes the compiler do additional type checks: now we're guaranteed that the boot code will handle all boot types and no invalid boot type will be possible.
2017-05-27 15:43:40 +02:00
// Set up paths
const std::string region_dir = GetDirectoryForRegion(ToGameCubeRegion(m_region));
CheckMemcardPath(SConfig::GetInstance().m_strMemoryCardA, region_dir, true);
CheckMemcardPath(SConfig::GetInstance().m_strMemoryCardB, region_dir, false);
m_strSRAM = File::GetUserPath(F_GCSRAM_IDX);
m_strBootROM = GetBootROMPath(region_dir);
return true;
}
void SConfig::CheckMemcardPath(std::string& memcardPath, const std::string& gameRegion,
bool isSlotA)
{
std::string ext("." + gameRegion + ".raw");
if (memcardPath.empty())
{
// Use default memcard path if there is no user defined name
std::string defaultFilename = isSlotA ? GC_MEMCARDA : GC_MEMCARDB;
memcardPath = File::GetUserPath(D_GCUSER_IDX) + defaultFilename + ext;
}
else
{
std::string filename = memcardPath;
std::string region = filename.substr(filename.size() - 7, 3);
bool hasregion = false;
hasregion |= region.compare(USA_DIR) == 0;
hasregion |= region.compare(JAP_DIR) == 0;
hasregion |= region.compare(EUR_DIR) == 0;
if (!hasregion)
{
// filename doesn't have region in the extension
if (File::Exists(filename))
{
// If the old file exists we are polite and ask if we should copy it
std::string oldFilename = filename;
filename.replace(filename.size() - 4, 4, ext);
if (PanicYesNoT("Memory Card filename in Slot %c is incorrect\n"
"Region not specified\n\n"
"Slot %c path was changed to\n"
"%s\n"
"Would you like to copy the old file to this new location?\n",
isSlotA ? 'A' : 'B', isSlotA ? 'A' : 'B', filename.c_str()))
{
if (!File::Copy(oldFilename, filename))
PanicAlertT("Copy failed");
}
}
memcardPath = filename; // Always correct the path!
}
else if (region.compare(gameRegion) != 0)
{
// filename has region, but it's not == gameRegion
// Just set the correct filename, the EXI Device will create it if it doesn't exist
memcardPath = filename.replace(filename.size() - ext.size(), ext.size(), ext);
}
}
}
DiscIO::Language SConfig::GetCurrentLanguage(bool wii) const
{
int language_value;
if (wii)
language_value = Config::Get(Config::SYSCONF_LANGUAGE);
else
language_value = SConfig::GetInstance().SelectedLanguage + 1;
DiscIO::Language language = static_cast<DiscIO::Language>(language_value);
// Get rid of invalid values (probably doesn't matter, but might as well do it)
if (language > DiscIO::Language::Unknown || language < DiscIO::Language::Japanese)
language = DiscIO::Language::Unknown;
return language;
}
IniFile SConfig::LoadDefaultGameIni() const
{
return LoadDefaultGameIni(GetGameID(), m_revision);
}
IniFile SConfig::LoadLocalGameIni() const
{
return LoadLocalGameIni(GetGameID(), m_revision);
}
IniFile SConfig::LoadGameIni() const
{
return LoadGameIni(GetGameID(), m_revision);
}
IniFile SConfig::LoadDefaultGameIni(const std::string& id, std::optional<u16> revision)
{
IniFile game_ini;
for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(id, revision))
game_ini.Load(File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + filename, true);
return game_ini;
}
IniFile SConfig::LoadLocalGameIni(const std::string& id, std::optional<u16> revision)
{
IniFile game_ini;
for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(id, revision))
game_ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + filename, true);
return game_ini;
}
IniFile SConfig::LoadGameIni(const std::string& id, std::optional<u16> revision)
{
IniFile game_ini;
for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(id, revision))
game_ini.Load(File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + filename, true);
for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(id, revision))
game_ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + filename, true);
return game_ini;
}