From 22992ae41e8f979149f5a1ec895519397fce490a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 27 May 2017 15:43:40 +0200 Subject: [PATCH] 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. --- Source/Android/jni/MainAndroid.cpp | 3 +- Source/Core/Core/Boot/Boot.cpp | 431 ++++++++++++---------- Source/Core/Core/Boot/Boot.h | 59 ++- Source/Core/Core/Boot/Boot_WiiWAD.cpp | 8 + Source/Core/Core/BootManager.cpp | 26 +- Source/Core/Core/BootManager.h | 5 +- Source/Core/Core/ConfigManager.cpp | 231 ++++-------- Source/Core/Core/ConfigManager.h | 28 +- Source/Core/Core/Core.cpp | 48 ++- Source/Core/Core/Core.h | 5 +- Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp | 3 +- Source/Core/Core/IOS/ES/Views.cpp | 2 +- Source/Core/Core/Movie.cpp | 28 +- Source/Core/Core/Movie.h | 6 +- Source/Core/DolphinNoGUI/MainNoGUI.cpp | 3 +- Source/Core/DolphinQt2/MainWindow.cpp | 3 +- Source/Core/DolphinWX/Frame.h | 5 +- Source/Core/DolphinWX/FrameTools.cpp | 14 +- 18 files changed, 468 insertions(+), 440 deletions(-) diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 9d3dff94c4..350b78b361 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -25,6 +25,7 @@ #include "Common/Logging/LogManager.h" #include "Common/MsgHandler.h" +#include "Core/Boot/Boot.h" #include "Core/BootManager.h" #include "Core/ConfigManager.h" #include "Core/Core.h" @@ -794,7 +795,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv* // No use running the loop when booting fails s_have_wm_user_stop = false; - if (BootManager::BootCore(s_filename.c_str(), SConfig::BOOT_DEFAULT)) + if (BootManager::BootCore(BootParameters::GenerateFromFile(s_filename))) { static constexpr int TIMEOUT = 10000; static constexpr int WAIT_STEP = 25; diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 9ca576721b..43296eb784 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -4,13 +4,16 @@ #include "Core/Boot/Boot.h" +#include #include #include +#include #include #include #include "Common/Align.h" +#include "Common/CDUtils.h" #include "Common/CommonPaths.h" #include "Common/CommonTypes.h" #include "Common/FileUtil.h" @@ -22,6 +25,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/Debugger/Debugger_SymbolMap.h" +#include "Core/FifoPlayer/FifoPlayer.h" #include "Core/HLE/HLE.h" #include "Core/HW/DVD/DVDInterface.h" #include "Core/HW/EXI/EXI_DeviceIPL.h" @@ -39,6 +43,76 @@ #include "DiscIO/NANDContentLoader.h" #include "DiscIO/Volume.h" +BootParameters::BootParameters(Parameters&& parameters_) : parameters(std::move(parameters_)) +{ +} + +std::unique_ptr BootParameters::GenerateFromFile(const std::string& path) +{ + const bool is_drive = cdio_is_cdrom(path); + // Check if the file exist, we may have gotten it from a --elf command line + // that gave an incorrect file name + if (!is_drive && !File::Exists(path)) + { + PanicAlertT("The specified file \"%s\" does not exist", path.c_str()); + return {}; + } + + std::string extension; + SplitPath(path, nullptr, nullptr, &extension); + std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + + static const std::unordered_set disc_image_extensions = { + {".gcm", ".iso", ".tgc", ".wbfs", ".ciso", ".gcz"}}; + if (disc_image_extensions.find(extension) != disc_image_extensions.end() || is_drive) + { + auto volume = DiscIO::CreateVolumeFromFilename(path); + if (!volume) + { + if (is_drive) + { + PanicAlertT("Could not read \"%s\". " + "There is no disc in the drive or it is not a GameCube/Wii backup. " + "Please note that Dolphin cannot play games directly from the original " + "GameCube and Wii discs.", + path.c_str()); + } + else + { + PanicAlertT("\"%s\" is an invalid GCM/ISO file, or is not a GC/Wii ISO.", path.c_str()); + } + return {}; + } + return std::make_unique(Disc{path, std::move(volume)}); + } + + if (extension == ".elf" || extension == ".dol") + { + return std::make_unique( + Executable{path, extension == ".elf" ? Executable::Type::ELF : Executable::Type::DOL}); + } + + if (extension == ".dff") + return std::make_unique(DFF{path}); + + if (DiscIO::NANDContentManager::Access().GetNANDLoader(path).IsValid()) + return std::make_unique(NAND{path}); + + PanicAlertT("Could not recognize file %s", path.c_str()); + return {}; +} + +BootParameters::IPL::IPL(DiscIO::Region region_) : region(region_) +{ + const std::string directory = SConfig::GetInstance().GetDirectoryForRegion(region); + path = SConfig::GetInstance().GetBootROMPath(directory); +} + +BootParameters::IPL::IPL(DiscIO::Region region_, Disc&& disc_) : IPL(region_) +{ + disc = std::move(disc_); +} + // Inserts a disc into the emulated disc drive and returns a pointer to it. // The returned pointer must only be used while we are still booting, // because DVDThread can do whatever it wants to the disc after that. @@ -102,57 +176,24 @@ void CBoot::UpdateDebugger_MapLoaded() Host_NotifyMapLoaded(); } +// Get map file paths for the active title. bool CBoot::FindMapFile(std::string* existing_map_file, std::string* writable_map_file, std::string* title_id) { - std::string title_id_str; - size_t name_begin_index; - - SConfig& _StartupPara = SConfig::GetInstance(); - switch (_StartupPara.m_BootType) - { - case SConfig::BOOT_WII_NAND: - { - const DiscIO::NANDContentLoader& Loader = - DiscIO::NANDContentManager::Access().GetNANDLoader(_StartupPara.m_strFilename); - if (Loader.IsValid()) - { - u64 TitleID = Loader.GetTMD().GetTitleId(); - title_id_str = StringFromFormat("%08X_%08X", (u32)(TitleID >> 32) & 0xFFFFFFFF, - (u32)TitleID & 0xFFFFFFFF); - } - break; - } - - case SConfig::BOOT_ELF: - case SConfig::BOOT_DOL: - // Strip the .elf/.dol file extension and directories before the name - name_begin_index = _StartupPara.m_strFilename.find_last_of("/") + 1; - if ((_StartupPara.m_strFilename.find_last_of("\\") + 1) > name_begin_index) - { - name_begin_index = _StartupPara.m_strFilename.find_last_of("\\") + 1; - } - title_id_str = _StartupPara.m_strFilename.substr( - name_begin_index, _StartupPara.m_strFilename.size() - 4 - name_begin_index); - break; - - default: - title_id_str = _StartupPara.GetGameID(); - break; - } + const std::string game_id = SConfig::GetInstance().GetGameID(); if (writable_map_file) - *writable_map_file = File::GetUserPath(D_MAPS_IDX) + title_id_str + ".map"; + *writable_map_file = File::GetUserPath(D_MAPS_IDX) + game_id + ".map"; if (title_id) - *title_id = title_id_str; + *title_id = game_id; bool found = false; static const std::string maps_directories[] = {File::GetUserPath(D_MAPS_IDX), File::GetSysDirectory() + MAPS_DIR DIR_SEP}; for (size_t i = 0; !found && i < ArraySize(maps_directories); ++i) { - std::string path = maps_directories[i] + title_id_str + ".map"; + std::string path = maps_directories[i] + game_id + ".map"; if (File::Exists(path)) { found = true; @@ -270,199 +311,187 @@ bool CBoot::Load_BS2(const std::string& boot_rom_filename) return true; } -// Third boot step after BootManager and Core. See Call schedule in BootManager.cpp -bool CBoot::BootUp() +static const DiscIO::Volume* SetDefaultDisc() { - SConfig& _StartupPara = SConfig::GetInstance(); + const SConfig& config = SConfig::GetInstance(); + // load default image or create virtual drive from directory + if (!config.m_strDVDRoot.empty()) + return SetDisc(DiscIO::CreateVolumeFromDirectory(config.m_strDVDRoot, config.bWii)); + if (!config.m_strDefaultISO.empty()) + return SetDisc(DiscIO::CreateVolumeFromFilename(config.m_strDefaultISO)); + return nullptr; +} - if (_StartupPara.m_BootType == SConfig::BOOT_BS2) - NOTICE_LOG(BOOT, "Booting %s", _StartupPara.m_strBootROM.c_str()); - else - NOTICE_LOG(BOOT, "Booting %s", _StartupPara.m_strFilename.c_str()); +// Third boot step after BootManager and Core. See Call schedule in BootManager.cpp +bool CBoot::BootUp(std::unique_ptr boot) +{ + SConfig& config = SConfig::GetInstance(); g_symbolDB.Clear(); // PAL Wii uses NTSC framerate and linecount in 60Hz modes - VideoInterface::Preset(DiscIO::IsNTSC(_StartupPara.m_region) || - (_StartupPara.bWii && _StartupPara.bPAL60)); + VideoInterface::Preset(DiscIO::IsNTSC(config.m_region) || (config.bWii && config.bPAL60)); - switch (_StartupPara.m_BootType) + struct BootTitle { - case SConfig::BOOT_ISO: - { - const DiscIO::Volume* volume = - SetDisc(DiscIO::CreateVolumeFromFilename(_StartupPara.m_strFilename)); - - if (!volume) - return false; - - if ((volume->GetVolumeType() == DiscIO::Platform::WII_DISC) != _StartupPara.bWii) + BootTitle() : config(SConfig::GetInstance()) {} + bool operator()(const BootParameters::Disc& disc) const { - PanicAlertT("Warning - starting ISO in wrong console mode!"); - } + NOTICE_LOG(BOOT, "Booting from disc: %s", disc.path.c_str()); + const DiscIO::Volume* volume = SetDisc(DiscIO::CreateVolumeFromFilename(disc.path)); - _StartupPara.bWii = volume->GetVolumeType() == DiscIO::Platform::WII_DISC; + if (!volume) + return false; - // We HLE the bootrom if requested or if LLEing it fails - if (_StartupPara.bHLE_BS2 || !Load_BS2(_StartupPara.m_strBootROM)) - EmulatedBS2(_StartupPara.bWii, volume); + if (!EmulatedBS2(config.bWii, volume)) + return false; - PatchEngine::LoadPatches(); - - // Scan for common HLE functions - if (_StartupPara.bHLE_BS2 && !_StartupPara.bEnableDebugging) - { - PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB); - SignatureDB db(SignatureDB::HandlerType::DSY); - if (db.Load(File::GetSysDirectory() + TOTALDB)) + // Scan for common HLE functions + if (!config.bEnableDebugging) { - db.Apply(&g_symbolDB); - HLE::PatchFunctions(); - db.Clear(); + PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB); + SignatureDB db(SignatureDB::HandlerType::DSY); + if (db.Load(File::GetSysDirectory() + TOTALDB)) + { + db.Apply(&g_symbolDB); + HLE::PatchFunctions(); + db.Clear(); + } } + + // Try to load the symbol map if there is one, and then scan it for + // and eventually replace code + if (LoadMapFromFilename()) + HLE::PatchFunctions(); + + return true; } - // Try to load the symbol map if there is one, and then scan it for - // and eventually replace code - if (LoadMapFromFilename()) - HLE::PatchFunctions(); - - break; - } - - case SConfig::BOOT_DOL: - { - CDolLoader dolLoader(_StartupPara.m_strFilename); - if (!dolLoader.IsValid()) - return false; - - // Check if we have gotten a Wii file or not - bool dolWii = dolLoader.IsWii(); - if (dolWii != _StartupPara.bWii) + bool operator()(const BootParameters::Executable& executable) const { - PanicAlertT("Warning - starting DOL in wrong console mode!"); + NOTICE_LOG(BOOT, "Booting from executable: %s", executable.path.c_str()); + + // TODO: needs more cleanup. + if (executable.type == BootParameters::Executable::Type::DOL) + { + CDolLoader dolLoader(executable.path); + if (!dolLoader.IsValid()) + return false; + + const DiscIO::Volume* volume = nullptr; + if (!config.m_strDVDRoot.empty()) + { + NOTICE_LOG(BOOT, "Setting DVDRoot %s", config.m_strDVDRoot.c_str()); + volume = SetDisc(DiscIO::CreateVolumeFromDirectory( + config.m_strDVDRoot, config.bWii, config.m_strApploader, executable.path)); + } + else if (!config.m_strDefaultISO.empty()) + { + NOTICE_LOG(BOOT, "Loading default ISO %s", config.m_strDefaultISO.c_str()); + volume = SetDisc(DiscIO::CreateVolumeFromFilename(config.m_strDefaultISO)); + } + + // Poor man's bootup + if (config.bWii) + { + HID4.SBE = 1; + SetupMSR(); + SetupBAT(config.bWii); + + // Because there is no TMD to get the requested system (IOS) version from, + // we default to IOS58, which is the version used by the Homebrew Channel. + SetupWiiMemory(volume, 0x000000010000003a); + } + else + { + EmulatedBS2_GC(volume, true); + } + + Load_FST(config.bWii, volume); + dolLoader.Load(); + PC = dolLoader.GetEntryPoint(); + + if (LoadMapFromFilename()) + HLE::PatchFunctions(); + } + + if (executable.type == BootParameters::Executable::Type::ELF) + { + const DiscIO::Volume* volume = SetDefaultDisc(); + + // Poor man's bootup + if (config.bWii) + { + // Because there is no TMD to get the requested system (IOS) version from, + // we default to IOS58, which is the version used by the Homebrew Channel. + SetupWiiMemory(volume, 0x000000010000003a); + } + else + { + EmulatedBS2_GC(volume, true); + } + + Load_FST(config.bWii, volume); + if (!Boot_ELF(executable.path)) + return false; + + // Note: Boot_ELF calls HLE::PatchFunctions() + + UpdateDebugger_MapLoaded(); + Dolphin_Debugger::AddAutoBreakpoints(); + } + + return true; } - const DiscIO::Volume* volume = nullptr; - if (!_StartupPara.m_strDVDRoot.empty()) + bool operator()(const BootParameters::NAND& nand) const { - NOTICE_LOG(BOOT, "Setting DVDRoot %s", _StartupPara.m_strDVDRoot.c_str()); - volume = SetDisc(DiscIO::CreateVolumeFromDirectory(_StartupPara.m_strDVDRoot, dolWii, - _StartupPara.m_strApploader, - _StartupPara.m_strFilename)); + NOTICE_LOG(BOOT, "Booting from NAND: %s", nand.content_path.c_str()); + SetDefaultDisc(); + return Boot_WiiWAD(nand.content_path); } - else if (!_StartupPara.m_strDefaultISO.empty()) + + bool operator()(const BootParameters::IPL& ipl) const { - NOTICE_LOG(BOOT, "Loading default ISO %s", _StartupPara.m_strDefaultISO.c_str()); - volume = SetDisc(DiscIO::CreateVolumeFromFilename(_StartupPara.m_strDefaultISO)); + NOTICE_LOG(BOOT, "Booting GC IPL: %s", ipl.path.c_str()); + if (!File::Exists(ipl.path)) + { + if (ipl.disc) + PanicAlertT("Cannot start the game, because the GC IPL could not be found."); + else + PanicAlertT("Cannot find the GC IPL."); + return false; + } + + if (!Load_BS2(ipl.path)) + return false; + + if (ipl.disc) + { + NOTICE_LOG(BOOT, "Inserting disc: %s", ipl.disc->path.c_str()); + SetDisc(DiscIO::CreateVolumeFromFilename(ipl.disc->path)); + } + + if (LoadMapFromFilename()) + HLE::PatchFunctions(); + + return true; } - // Poor man's bootup - if (dolWii) + bool operator()(const BootParameters::DFF& dff) const { - HID4.SBE = 1; - SetupMSR(); - SetupBAT(dolWii); - - // Because there is no TMD to get the requested system (IOS) version from, - // we default to IOS58, which is the version used by the Homebrew Channel. - SetupWiiMemory(volume, 0x000000010000003a); - } - else - { - EmulatedBS2_GC(volume, true); + NOTICE_LOG(BOOT, "Booting DFF: %s", dff.dff_path.c_str()); + return FifoPlayer::GetInstance().Open(dff.dff_path); } - Load_FST(dolWii, volume); - dolLoader.Load(); - PC = dolLoader.GetEntryPoint(); + private: + const SConfig& config; + }; - if (LoadMapFromFilename()) - HLE::PatchFunctions(); - - break; - } - - case SConfig::BOOT_ELF: - { - const DiscIO::Volume* volume = nullptr; - - // load image or create virtual drive from directory - if (!_StartupPara.m_strDVDRoot.empty()) - { - NOTICE_LOG(BOOT, "Setting DVDRoot %s", _StartupPara.m_strDVDRoot.c_str()); - volume = - SetDisc(DiscIO::CreateVolumeFromDirectory(_StartupPara.m_strDVDRoot, _StartupPara.bWii)); - } - else if (!_StartupPara.m_strDefaultISO.empty()) - { - NOTICE_LOG(BOOT, "Loading default ISO %s", _StartupPara.m_strDefaultISO.c_str()); - volume = SetDisc(DiscIO::CreateVolumeFromFilename(_StartupPara.m_strDefaultISO)); - } - - // Poor man's bootup - if (_StartupPara.bWii) - { - // Because there is no TMD to get the requested system (IOS) version from, - // we default to IOS58, which is the version used by the Homebrew Channel. - SetupWiiMemory(volume, 0x000000010000003a); - } - else - { - EmulatedBS2_GC(volume, true); - } - - Load_FST(_StartupPara.bWii, volume); - if (!Boot_ELF(_StartupPara.m_strFilename)) - return false; - - // Note: Boot_ELF calls HLE::PatchFunctions() - - UpdateDebugger_MapLoaded(); - Dolphin_Debugger::AddAutoBreakpoints(); - break; - } - - case SConfig::BOOT_WII_NAND: - Boot_WiiWAD(_StartupPara.m_strFilename); - - PatchEngine::LoadPatches(); - - // Not bootstrapped yet, can't translate memory addresses. Thus, prevents Symbol Map usage. - // if (LoadMapFromFilename()) - // HLE::PatchFunctions(); - - // load default image or create virtual drive from directory - if (!_StartupPara.m_strDVDRoot.empty()) - SetDisc(DiscIO::CreateVolumeFromDirectory(_StartupPara.m_strDVDRoot, true)); - else if (!_StartupPara.m_strDefaultISO.empty()) - SetDisc(DiscIO::CreateVolumeFromFilename(_StartupPara.m_strDefaultISO)); - - break; - - // Bootstrap 2 (AKA: Initial Program Loader, "BIOS") - case SConfig::BOOT_BS2: - { - if (!Load_BS2(_StartupPara.m_strBootROM)) - return false; - - if (LoadMapFromFilename()) - HLE::PatchFunctions(); - - break; - } - - case SConfig::BOOT_DFF: - // do nothing - break; - - default: - { - PanicAlertT("Tried to load an unknown file type."); + if (!std::visit(BootTitle(), boot->parameters)) return false; - } - } + PatchEngine::LoadPatches(); HLE::PatchFixedFunctions(); return true; } diff --git a/Source/Core/Core/Boot/Boot.h b/Source/Core/Core/Boot/Boot.h index 42c71b199f..742bb056e5 100644 --- a/Source/Core/Core/Boot/Boot.h +++ b/Source/Core/Core/Boot/Boot.h @@ -5,15 +5,13 @@ #pragma once #include +#include #include +#include #include "Common/CommonTypes.h" - -namespace DiscIO -{ -class Volume; -struct Partition; -} +#include "DiscIO/Enums.h" +#include "DiscIO/Volume.h" struct RegionSetting { @@ -23,10 +21,57 @@ struct RegionSetting const std::string code; }; +struct BootParameters +{ + struct Disc + { + std::string path; + std::unique_ptr volume; + }; + + struct Executable + { + enum class Type + { + DOL, + ELF, + }; + std::string path; + Type type; + }; + + struct NAND + { + std::string content_path; + }; + + struct IPL + { + explicit IPL(DiscIO::Region region_); + IPL(DiscIO::Region region_, Disc&& disc_); + std::string path; + DiscIO::Region region; + // It is possible to boot the IPL with a disc inserted (with "skip IPL" disabled). + std::optional disc; + }; + + struct DFF + { + std::string dff_path; + }; + + static std::unique_ptr GenerateFromFile(const std::string& path); + + using Parameters = std::variant; + BootParameters(Parameters&& parameters_); + + Parameters parameters; +}; + class CBoot { public: - static bool BootUp(); + static bool BootUp(std::unique_ptr boot); static bool IsElfWii(const std::string& filename); // Tries to find a map file for the current game by looking first in the diff --git a/Source/Core/Core/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Boot/Boot_WiiWAD.cpp index 54501a1638..889496ccb2 100644 --- a/Source/Core/Core/Boot/Boot_WiiWAD.cpp +++ b/Source/Core/Core/Boot/Boot_WiiWAD.cpp @@ -11,6 +11,7 @@ #include "Common/CommonPaths.h" #include "Common/CommonTypes.h" #include "Common/FileUtil.h" +#include "Common/MsgHandler.h" #include "Common/NandPaths.h" #include "Core/Boot/Boot.h" @@ -78,6 +79,13 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename) return false; u64 titleID = ContentLoader.GetTMD().GetTitleId(); + + if (!IOS::ES::IsChannel(titleID)) + { + PanicAlertT("This WAD is not bootable."); + return false; + } + // create data directory File::CreateFullPath(Common::GetTitleDataPath(titleID, Common::FROM_SESSION_ROOT)); diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index 6262fd94dd..7738e0897c 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -31,6 +31,7 @@ #include "Common/MsgHandler.h" #include "Common/StringUtil.h" +#include "Core/Boot/Boot.h" #include "Core/Config/Config.h" #include "Core/ConfigLoaders/GameConfigLoader.h" #include "Core/ConfigLoaders/NetPlayConfigLoader.h" @@ -222,23 +223,23 @@ static GPUDeterminismMode ParseGPUDeterminismMode(const std::string& mode) } // Boot the ISO or file -bool BootCore(const std::string& filename, SConfig::EBootBS2 type) +bool BootCore(std::unique_ptr boot) { + if (!boot) + return false; + SConfig& StartUp = SConfig::GetInstance(); - StartUp.m_BootType = SConfig::BOOT_ISO; - StartUp.m_strFilename = filename; StartUp.bRunCompareClient = false; StartUp.bRunCompareServer = false; config_cache.SaveConfig(StartUp); - // If for example the ISO file is bad we return here - if (!StartUp.AutoSetup(type)) + if (!StartUp.SetPathsAndGameMetadata(*boot)) return false; // Load game specific settings - if (type == SConfig::BOOT_DEFAULT) + if (!std::holds_alternative(boot->parameters)) { std::string game_id = SConfig::GetInstance().GetGameID(); u16 revision = SConfig::GetInstance().GetRevision(); @@ -400,15 +401,14 @@ bool BootCore(const std::string& filename, SConfig::EBootBS2 type) if (StartUp.bWii) StartUp.SaveSettingsToSysconf(); - // Run the game - // Init the core - if (!Core::Init()) + const bool load_ipl = !StartUp.bWii && !StartUp.bHLE_BS2 && + std::holds_alternative(boot->parameters); + if (load_ipl) { - PanicAlertT("Couldn't init the core.\nCheck your configuration."); - return false; + return Core::Init(std::make_unique(BootParameters::IPL{ + StartUp.m_region, std::move(std::get(boot->parameters))})); } - - return true; + return Core::Init(std::move(boot)); } void Stop() diff --git a/Source/Core/Core/BootManager.h b/Source/Core/Core/BootManager.h index bb7b7cae99..a068247e50 100644 --- a/Source/Core/Core/BootManager.h +++ b/Source/Core/Core/BootManager.h @@ -4,13 +4,16 @@ #pragma once +#include #include #include "Core/ConfigManager.h" +struct BootParameters; + namespace BootManager { -bool BootCore(const std::string& filename, SConfig::EBootBS2 type); +bool BootCore(std::unique_ptr parameters); // Stop the emulation core and restore the configuration. void Stop(); diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 400bbfc581..342cb60527 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "AudioCommon/AudioCommon.h" @@ -881,165 +882,95 @@ std::string SConfig::GetBootROMPath(const std::string& region_directory) const return path; } -// Sets m_region to the region parameter, or to PAL if the region parameter -// is invalid. Set directory_name to the value returned by GetDirectoryForRegion -// for m_region. Returns false if the region parameter is invalid. -bool SConfig::SetRegion(DiscIO::Region region, std::string* directory_name) +struct SetGameMetadata { + 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::WII_DISC; + config->m_disc_booted_from_game_list = true; + *region = disc.volume->GetRegion(); + return true; + } + + bool operator()(const BootParameters::Executable& executable) const + { + if (executable.type == BootParameters::Executable::Type::DOL) + config->bWii = CDolLoader{executable.path}.IsWii(); + if (executable.type == BootParameters::Executable::Type::ELF) + config->bWii = CBoot::IsElfWii(executable.path); + + // TODO: Right now GC homebrew boots in NTSC and Wii homebrew in PAL. + // This is intentional so that Wii homebrew can boot in both 50Hz and 60Hz, + // without forcing all GC homebrew to 50Hz. + // In the future, it probably makes sense to add a Region setting for homebrew somewhere in + // the emulator config. + *region = config->bWii ? DiscIO::Region::PAL : DiscIO::Region::NTSC_U; + return true; + } + + bool operator()(const BootParameters::NAND& nand) const + { + const auto& loader = DiscIO::NANDContentManager::Access().GetNANDLoader(nand.content_path); + if (!loader.IsValid()) + return false; + + const IOS::ES::TMDReader& tmd = loader.GetTMD(); + + config->SetRunningGameMetadata(tmd); + config->bWii = true; + *region = tmd.GetRegion(); + return true; + } + + bool operator()(const BootParameters::IPL& ipl) const + { + config->bWii = false; + *region = ipl.region; + return true; + } + + bool operator()(const BootParameters::DFF& dff) const + { + std::unique_ptr dff_file(FifoDataFile::Load(dff.dff_path, true)); + if (!dff_file) + return false; + + config->bWii = dff_file->GetIsWii(); + *region = DiscIO::Region::NTSC_U; + return true; + } + +private: + SConfig* config; + DiscIO::Region* region; +}; + +bool SConfig::SetPathsAndGameMetadata(const BootParameters& boot) +{ + m_is_mios = false; + m_disc_booted_from_game_list = false; + DiscIO::Region region; + if (!std::visit(SetGameMetadata(this, ®ion), boot.parameters)) + return false; + + // Set up region const char* retrieved_region_dir = GetDirectoryForRegion(region); m_region = retrieved_region_dir ? region : DiscIO::Region::PAL; - *directory_name = retrieved_region_dir ? retrieved_region_dir : EUR_DIR; - return !!retrieved_region_dir; -} - -bool SConfig::AutoSetup(EBootBS2 _BootBS2) -{ - std::string set_region_dir(EUR_DIR); - - switch (_BootBS2) + const std::string set_region_dir = retrieved_region_dir ? retrieved_region_dir : EUR_DIR; + if (!retrieved_region_dir && + !PanicYesNoT("Your GCM/ISO file seems to be invalid (invalid country)." + "\nContinue with PAL region?")) { - case BOOT_DEFAULT: - { - bool bootDrive = cdio_is_cdrom(m_strFilename); - // Check if the file exist, we may have gotten it from a --elf command line - // that gave an incorrect file name - if (!bootDrive && !File::Exists(m_strFilename)) - { - PanicAlertT("The specified file \"%s\" does not exist", m_strFilename.c_str()); - return false; - } - - std::string Extension; - SplitPath(m_strFilename, nullptr, nullptr, &Extension); - if (!strcasecmp(Extension.c_str(), ".gcm") || !strcasecmp(Extension.c_str(), ".iso") || - !strcasecmp(Extension.c_str(), ".tgc") || !strcasecmp(Extension.c_str(), ".wbfs") || - !strcasecmp(Extension.c_str(), ".ciso") || !strcasecmp(Extension.c_str(), ".gcz") || - bootDrive) - { - m_BootType = BOOT_ISO; - std::unique_ptr pVolume(DiscIO::CreateVolumeFromFilename(m_strFilename)); - if (pVolume == nullptr) - { - if (bootDrive) - PanicAlertT("Could not read \"%s\". " - "There is no disc in the drive or it is not a GameCube/Wii backup. " - "Please note that Dolphin cannot play games directly from the original " - "GameCube and Wii discs.", - m_strFilename.c_str()); - else - PanicAlertT("\"%s\" is an invalid GCM/ISO file, or is not a GC/Wii ISO.", - m_strFilename.c_str()); - return false; - } - SetRunningGameMetadata(*pVolume, pVolume->GetGamePartition()); - - // Check if we have a Wii disc - bWii = pVolume->GetVolumeType() == DiscIO::Platform::WII_DISC; - - if (!SetRegion(pVolume->GetRegion(), &set_region_dir)) - if (!PanicYesNoT("Your GCM/ISO file seems to be invalid (invalid country)." - "\nContinue with PAL region?")) - return false; - } - else if (!strcasecmp(Extension.c_str(), ".elf")) - { - bWii = CBoot::IsElfWii(m_strFilename); - // TODO: Right now GC homebrew boots in NTSC and Wii homebrew in PAL. - // This is intentional so that Wii homebrew can boot in both 50Hz and 60Hz, without forcing - // all GC homebrew to 50Hz. - // In the future, it probably makes sense to add a Region setting for homebrew somewhere in - // the emulator config. - SetRegion(bWii ? DiscIO::Region::PAL : DiscIO::Region::NTSC_U, &set_region_dir); - m_BootType = BOOT_ELF; - } - else if (!strcasecmp(Extension.c_str(), ".dol")) - { - CDolLoader dolfile(m_strFilename); - bWii = dolfile.IsWii(); - // TODO: See the ELF code above. - SetRegion(bWii ? DiscIO::Region::PAL : DiscIO::Region::NTSC_U, &set_region_dir); - m_BootType = BOOT_DOL; - } - else if (!strcasecmp(Extension.c_str(), ".dff")) - { - bWii = true; - SetRegion(DiscIO::Region::NTSC_U, &set_region_dir); - m_BootType = BOOT_DFF; - - std::unique_ptr ddfFile(FifoDataFile::Load(m_strFilename, true)); - - if (ddfFile) - { - bWii = ddfFile->GetIsWii(); - } - } - else if (DiscIO::NANDContentManager::Access().GetNANDLoader(m_strFilename).IsValid()) - { - const DiscIO::NANDContentLoader& content_loader = - DiscIO::NANDContentManager::Access().GetNANDLoader(m_strFilename); - const IOS::ES::TMDReader& tmd = content_loader.GetTMD(); - - if (!IOS::ES::IsChannel(tmd.GetTitleId())) - { - PanicAlertT("This WAD is not bootable."); - return false; - } - - SetRegion(tmd.GetRegion(), &set_region_dir); - SetRunningGameMetadata(tmd); - - bWii = true; - m_BootType = BOOT_WII_NAND; - } - else - { - PanicAlertT("Could not recognize ISO file %s", m_strFilename.c_str()); - return false; - } - } - break; - - case BOOT_BS2_USA: - SetRegion(DiscIO::Region::NTSC_U, &set_region_dir); - m_strFilename.clear(); - m_BootType = SConfig::BOOT_BS2; - break; - - case BOOT_BS2_JAP: - SetRegion(DiscIO::Region::NTSC_J, &set_region_dir); - m_strFilename.clear(); - m_BootType = SConfig::BOOT_BS2; - break; - - case BOOT_BS2_EUR: - SetRegion(DiscIO::Region::PAL, &set_region_dir); - m_strFilename.clear(); - m_BootType = SConfig::BOOT_BS2; - break; + return false; } - // Setup paths + // Set up paths CheckMemcardPath(SConfig::GetInstance().m_strMemoryCardA, set_region_dir, true); CheckMemcardPath(SConfig::GetInstance().m_strMemoryCardB, set_region_dir, false); m_strSRAM = File::GetUserPath(F_GCSRAM_IDX); - if (!bWii) - { - if (!bHLE_BS2) - { - m_strBootROM = GetBootROMPath(set_region_dir); - - if (!File::Exists(m_strBootROM)) - { - WARN_LOG(BOOT, "Bootrom file %s not found - using HLE.", m_strBootROM.c_str()); - bHLE_BS2 = true; - } - } - } - else if (bWii && !bHLE_BS2) - { - WARN_LOG(BOOT, "GC bootrom file will not be loaded for Wii mode."); - bHLE_BS2 = true; - } + m_strBootROM = GetBootROMPath(set_region_dir); return true; } diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index 5102d400ba..3fd85fdfb9 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -51,6 +51,8 @@ enum GPUDeterminismMode GPU_DETERMINISM_FAKE_COMPLETION, }; +struct BootParameters; + struct SConfig : NonCopyable { // Wii Devices @@ -182,25 +184,6 @@ struct SConfig : NonCopyable bool bEnableCustomRTC; u32 m_customRTCValue; - enum EBootBS2 - { - BOOT_DEFAULT, - BOOT_BS2_JAP, - BOOT_BS2_USA, - BOOT_BS2_EUR, - }; - - enum EBootType - { - BOOT_ISO, - BOOT_ELF, - BOOT_DOL, - BOOT_WII_NAND, - BOOT_BS2, - BOOT_DFF - }; - - EBootType m_BootType; DiscIO::Region m_region; std::string m_strVideoBackend; @@ -210,7 +193,6 @@ struct SConfig : NonCopyable GPUDeterminismMode m_GPUDeterminismMode; // files - std::string m_strFilename; std::string m_strBootROM; std::string m_strSRAM; std::string m_strDefaultISO; @@ -220,6 +202,9 @@ struct SConfig : NonCopyable std::string m_perfDir; + // TODO: remove this as soon as the ticket view hack in IOS/ES/Views is dropped. + bool m_disc_booted_from_game_list = false; + const std::string& GetGameID() const { return m_game_id; } const std::string& GetTitleDescription() const { return m_title_description; } u64 GetTitleID() const { return m_title_id; } @@ -231,7 +216,7 @@ struct SConfig : NonCopyable void LoadDefaults(); static const char* GetDirectoryForRegion(DiscIO::Region region); std::string GetBootROMPath(const std::string& region_directory) const; - bool AutoSetup(EBootBS2 _BootBS2); + bool SetPathsAndGameMetadata(const BootParameters& boot); void CheckMemcardPath(std::string& memcardPath, const std::string& gameRegion, bool isSlotA); DiscIO::Language GetCurrentLanguage(bool wii) const; @@ -389,7 +374,6 @@ private: void SetRunningGameMetadata(const std::string& game_id, u64 title_id, u16 revision, Core::TitleDatabase::TitleType type); - bool SetRegion(DiscIO::Region region, std::string* directory_name); static SConfig* m_Instance; diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 122289c5b0..bdddfbadb4 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef _WIN32 #include @@ -122,7 +123,7 @@ static void InitIsCPUKey() } #endif -static void EmuThread(); +static void EmuThread(std::unique_ptr boot); bool GetIsThrottlerTempDisabled() { @@ -221,7 +222,7 @@ bool WantsDeterminism() // This is called from the GUI thread. See the booting call schedule in // BootManager.cpp -bool Init() +bool Init(std::unique_ptr boot) { if (s_emu_thread.joinable()) { @@ -248,7 +249,7 @@ bool Init() s_window_handle = Host_GetRenderHandle(); // Start the emu thread - s_emu_thread = std::thread(EmuThread); + s_emu_thread = std::thread(EmuThread, std::move(boot)); return true; } @@ -412,21 +413,18 @@ static void FifoPlayerThread() } // Enter CPU run loop. When we leave it - we are done. - if (FifoPlayer::GetInstance().Open(_CoreParameter.m_strFilename)) + if (auto cpu_core = FifoPlayer::GetInstance().GetCPUCore()) { - if (auto cpu_core = FifoPlayer::GetInstance().GetCPUCore()) - { - PowerPC::InjectExternalCPUCore(cpu_core.get()); - s_is_started = true; + PowerPC::InjectExternalCPUCore(cpu_core.get()); + s_is_started = true; - CPUSetInitialExecutionState(); - CPU::Run(); + CPUSetInitialExecutionState(); + CPU::Run(); - s_is_started = false; - PowerPC::InjectExternalCPUCore(nullptr); - } - FifoPlayer::GetInstance().Close(); + s_is_started = false; + PowerPC::InjectExternalCPUCore(nullptr); } + FifoPlayer::GetInstance().Close(); // If we did not enter the CPU Run Loop above then run a fake one instead. // We need to be IsRunningAndStarted() for DolphinWX to stop us. @@ -450,7 +448,7 @@ static void FifoPlayerThread() // Initialize and create emulation thread // Call browser: Init():s_emu_thread(). // See the BootManager.cpp file description for a complete call schedule. -static void EmuThread() +static void EmuThread(std::unique_ptr boot) { const SConfig& core_parameter = SConfig::GetInstance(); s_is_booting.Set(); @@ -474,12 +472,11 @@ static void EmuThread() DisplayMessage("WARNING: running at non-native CPU clock! Game may not be stable.", 8000); DisplayMessage(cpu_info.brand_string, 8000); DisplayMessage(cpu_info.Summarize(), 8000); - DisplayMessage(core_parameter.m_strFilename, 3000); // For a time this acts as the CPU thread... DeclareAsCPUThread(); - Movie::Init(); + Movie::Init(*boot); Common::ScopeGuard movie_guard{Movie::Shutdown}; HW::Init(); @@ -560,7 +557,15 @@ static void EmuThread() // Load GCM/DOL/ELF whatever ... we boot with the interpreter core PowerPC::SetMode(PowerPC::CoreMode::Interpreter); - CBoot::BootUp(); + // Determine the CPU thread function + void (*cpuThreadFunc)(); + if (std::holds_alternative(boot->parameters)) + cpuThreadFunc = FifoPlayerThread; + else + cpuThreadFunc = CpuThread; + + if (!CBoot::BootUp(std::move(boot))) + return; // This adds the SyncGPU handler to CoreTiming, so now CoreTiming::Advance might block. Fifo::Prepare(); @@ -583,13 +588,6 @@ static void EmuThread() Host_UpdateDisasmDialog(); Host_UpdateMainFrame(); - // Determine the CPU thread function - void (*cpuThreadFunc)(void); - if (core_parameter.m_BootType == SConfig::BOOT_DFF) - cpuThreadFunc = FifoPlayerThread; - else - cpuThreadFunc = CpuThread; - // ENTER THE VIDEO THREAD LOOP if (core_parameter.bCPUThread) { diff --git a/Source/Core/Core/Core.h b/Source/Core/Core/Core.h index 89bdedb25c..78b5f5d6c7 100644 --- a/Source/Core/Core/Core.h +++ b/Source/Core/Core/Core.h @@ -11,11 +11,14 @@ #pragma once #include +#include #include #include #include "Common/CommonTypes.h" +struct BootParameters; + namespace Core { bool GetIsThrottlerTempDisabled(); @@ -31,7 +34,7 @@ enum class State Stopping }; -bool Init(); +bool Init(std::unique_ptr boot); void Stop(); void Shutdown(); diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp index 22544118c5..528ed351f5 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp @@ -98,7 +98,8 @@ CEXIIPL::CEXIIPL() : m_uPosition(0), m_uAddress(0), m_uRWOffset(0), m_FontsLoade // Create the IPL m_pIPL = static_cast(Common::AllocateMemoryPages(ROM_SIZE)); - if (SConfig::GetInstance().bHLE_BS2) + // The Wii doesn't have a copy of the IPL, only fonts. + if (SConfig::GetInstance().bWii || SConfig::GetInstance().bHLE_BS2) { // Copy header if (DiscIO::IsNTSC(SConfig::GetInstance().m_region)) diff --git a/Source/Core/Core/IOS/ES/Views.cpp b/Source/Core/Core/IOS/ES/Views.cpp index 6bdd730c20..9d1369ca79 100644 --- a/Source/Core/Core/IOS/ES/Views.cpp +++ b/Source/Core/Core/IOS/ES/Views.cpp @@ -38,7 +38,7 @@ static bool ShouldReturnFakeViewsForIOSes(u64 title_id, const TitleContext& cont const bool ios = IsTitleType(title_id, IOS::ES::TitleType::System) && title_id != TITLEID_SYSMENU; const bool disc_title = context.active && IOS::ES::IsDiscTitle(context.tmd.GetTitleId()); return Core::WantsDeterminism() || - (ios && SConfig::GetInstance().m_BootType == SConfig::BOOT_ISO && disc_title); + (ios && SConfig::GetInstance().m_disc_booted_from_game_list && disc_title); } IPCCommandResult ES::GetTicketViewCount(const IOCtlVRequest& request) diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index 207a047079..608638c39a 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "Common/Assert.h" @@ -23,6 +24,7 @@ #include "Common/NandPaths.h" #include "Common/StringUtil.h" #include "Common/Timer.h" +#include "Core/Boot/Boot.h" #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/CoreTiming.h" @@ -97,6 +99,8 @@ static std::string s_InputDisplay[8]; static GCManipFunction s_gc_manip_func; static WiiManipFunction s_wii_manip_func; +static std::string s_current_file_name; + // NOTE: Host / CPU Thread static void EnsureTmpInputSize(size_t bound) { @@ -216,11 +220,19 @@ void FrameUpdate() s_bPolled = false; } +static void CheckMD5(); +static void GetMD5(); + // called when game is booting up, even if no movie is active, // but potentially after BeginRecordingInput or PlayInput has been called. // NOTE: EmuThread -void Init() +void Init(const BootParameters& boot) { + if (std::holds_alternative(boot.parameters)) + s_current_file_name = std::get(boot.parameters).path; + else + s_current_file_name.clear(); + s_bPolled = false; s_bFrameStep = false; s_bSaveConfig = false; @@ -1551,8 +1563,11 @@ void GetSettings() static const mbedtls_md_info_t* s_md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); // NOTE: Entrypoint for own thread -void CheckMD5() +static void CheckMD5() { + if (s_current_file_name.empty()) + return; + for (int i = 0, n = 0; i < 16; ++i) { if (tmpHeader.md5[i] != 0) @@ -1564,7 +1579,7 @@ void CheckMD5() Core::DisplayMessage("Verifying checksum...", 2000); unsigned char gameMD5[16]; - mbedtls_md_file(s_md5_info, SConfig::GetInstance().m_strFilename.c_str(), gameMD5); + mbedtls_md_file(s_md5_info, s_current_file_name.c_str(), gameMD5); if (memcmp(gameMD5, s_MD5, 16) == 0) Core::DisplayMessage("Checksum of current game matches the recorded game.", 2000); @@ -1573,11 +1588,14 @@ void CheckMD5() } // NOTE: Entrypoint for own thread -void GetMD5() +static void GetMD5() { + if (s_current_file_name.empty()) + return; + Core::DisplayMessage("Calculating checksum of game file...", 2000); memset(s_MD5, 0, sizeof(s_MD5)); - mbedtls_md_file(s_md5_info, SConfig::GetInstance().m_strFilename.c_str(), s_MD5); + mbedtls_md_file(s_md5_info, s_current_file_name.c_str(), s_MD5); Core::DisplayMessage("Finished calculating checksum.", 2000); } diff --git a/Source/Core/Core/Movie.h b/Source/Core/Core/Movie.h index 84326dcdb6..d56e61eaad 100644 --- a/Source/Core/Core/Movie.h +++ b/Source/Core/Core/Movie.h @@ -9,6 +9,8 @@ #include "Common/CommonTypes.h" +struct BootParameters; + struct GCPadStatus; class PointerWrap; struct wiimote_key; @@ -110,7 +112,7 @@ static_assert(sizeof(DTMHeader) == 256, "DTMHeader should be 256 bytes"); void FrameUpdate(); void InputUpdate(); -void Init(); +void Init(const BootParameters& boot); void SetPolledDevice(); @@ -171,8 +173,6 @@ bool PlayWiimote(int wiimote, u8* data, const struct WiimoteEmu::ReportFeatures& void EndPlayInput(bool cont); void SaveRecording(const std::string& filename); void DoState(PointerWrap& p); -void CheckMD5(); -void GetMD5(); void Shutdown(); void CheckPadStatus(GCPadStatus* PadStatus, int controllerID); void CheckWiimoteStatus(int wiimote, u8* data, const struct WiimoteEmu::ReportFeatures& rptf, diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index 528f2aa0e0..988518724a 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -18,6 +18,7 @@ #include "Common/MsgHandler.h" #include "Core/Analytics.h" +#include "Core/Boot/Boot.h" #include "Core/BootManager.h" #include "Core/ConfigManager.h" #include "Core/Core.h" @@ -422,7 +423,7 @@ int main(int argc, char* argv[]) DolphinAnalytics::Instance()->ReportDolphinStart("nogui"); - if (!BootManager::BootCore(boot_filename, SConfig::BOOT_DEFAULT)) + if (!BootManager::BootCore(BootParameters::GenerateFromFile(boot_filename))) { fprintf(stderr, "Could not boot %s\n", boot_filename.c_str()); return 1; diff --git a/Source/Core/DolphinQt2/MainWindow.cpp b/Source/Core/DolphinQt2/MainWindow.cpp index a8049826f2..0c8b14ef8c 100644 --- a/Source/Core/DolphinQt2/MainWindow.cpp +++ b/Source/Core/DolphinQt2/MainWindow.cpp @@ -9,6 +9,7 @@ #include "Common/Common.h" +#include "Core/Boot/Boot.h" #include "Core/BootManager.h" #include "Core/ConfigManager.h" #include "Core/Core.h" @@ -287,7 +288,7 @@ void MainWindow::StartGame(const QString& path) return; } // Boot up, show an error if it fails to load the game. - if (!BootManager::BootCore(path.toStdString(), SConfig::BOOT_DEFAULT)) + if (!BootManager::BootCore(BootParameters::GenerateFromFile(path.toStdString()))) { QMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok); return; diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index a0635321f8..4d5a7282dd 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,8 @@ #include #endif +struct BootParameters; + // Class declarations class CGameListCtrl; class CCodeWindow; @@ -184,7 +187,7 @@ private: void InitializeTASDialogs(); void InitializeCoreCallbacks(); - void StartGame(const std::string& filename, SConfig::EBootBS2 type = SConfig::BOOT_DEFAULT); + void StartGame(std::unique_ptr boot); void SetDebuggerStartupParameters() const; // Utility diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 22f0096cb6..8ac6fd7e08 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -30,6 +30,7 @@ #include "Common/NandPaths.h" #include "Common/StringUtil.h" +#include "Core/Boot/Boot.h" #include "Core/BootManager.h" #include "Core/ConfigManager.h" #include "Core/Core.h" @@ -53,6 +54,7 @@ #include "Core/PowerPC/PowerPC.h" #include "Core/State.h" +#include "DiscIO/Enums.h" #include "DiscIO/NANDContentLoader.h" #include "DiscIO/NANDImporter.h" #include "DiscIO/VolumeWad.h" @@ -315,7 +317,7 @@ void CFrame::BootGame(const std::string& filename) } if (!bootfile.empty()) { - StartGame(bootfile); + StartGame(BootParameters::GenerateFromFile(bootfile)); } } @@ -627,7 +629,7 @@ void CFrame::ToggleDisplayMode(bool bFullscreen) } // Prepare the GUI to start the game. -void CFrame::StartGame(const std::string& filename, SConfig::EBootBS2 type) +void CFrame::StartGame(std::unique_ptr boot) { if (m_is_game_loading) return; @@ -705,7 +707,7 @@ void CFrame::StartGame(const std::string& filename, SConfig::EBootBS2 type) SetDebuggerStartupParameters(); - if (!BootManager::BootCore(filename, type)) + if (!BootManager::BootCore(std::move(boot))) { DoFullscreen(false); @@ -1169,17 +1171,17 @@ void CFrame::OnMemcard(wxCommandEvent& WXUNUSED(event)) void CFrame::OnLoadGameCubeIPLJAP(wxCommandEvent&) { - StartGame("", SConfig::BOOT_BS2_JAP); + StartGame(std::make_unique(BootParameters::IPL{DiscIO::Region::NTSC_J})); } void CFrame::OnLoadGameCubeIPLUSA(wxCommandEvent&) { - StartGame("", SConfig::BOOT_BS2_USA); + StartGame(std::make_unique(BootParameters::IPL{DiscIO::Region::NTSC_U})); } void CFrame::OnLoadGameCubeIPLEUR(wxCommandEvent&) { - StartGame("", SConfig::BOOT_BS2_EUR); + StartGame(std::make_unique(BootParameters::IPL{DiscIO::Region::PAL})); } void CFrame::OnExportAllSaves(wxCommandEvent& WXUNUSED(event))