mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-16 05:42:55 +00:00
This lets us reduce the number of USE_RETRO_ACHIEVEMENTS ifdefs in the code base, reducing visual clutter. In particular, needing an ifdef for each call to IsHardcodeModeActive was annoying to me. This also reduces the risk that someone writes code that accidentally fails to compile with USE_RETRO_ACHIEVEMENTS disabled. We could cut down on ifdefs even further by making HardcodeWarningWidget always exist, but that would result in non-trivial code ending up in the binary even with USE_RETRO_ACHIEVEMENTS disabled, so I'm leaving it out of this PR. It's not a lot of code though, so I might end up revisiting it at some point.
235 lines
7.8 KiB
C++
235 lines
7.8 KiB
C++
// Copyright 2011 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
// File description
|
|
// -------------
|
|
// Purpose of this file: Collect boot settings for Core::Init()
|
|
|
|
// Call sequence: This file has one of the first function called when a game is booted,
|
|
// the boot sequence in the code is:
|
|
|
|
// DolphinWX: FrameTools.cpp StartGame
|
|
// Core BootManager.cpp BootCore
|
|
// Core.cpp Init Thread creation
|
|
// EmuThread Calls CBoot::BootUp
|
|
// Boot.cpp CBoot::BootUp()
|
|
// CBoot::EmulatedBS2_Wii() / GC() or Load_BS2()
|
|
|
|
#include "Core/BootManager.h"
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <string>
|
|
|
|
#include <fmt/format.h>
|
|
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/Config/Config.h"
|
|
#include "Common/FileUtil.h"
|
|
#include "Common/IniFile.h"
|
|
#include "Common/Logging/Log.h"
|
|
|
|
#include "Core/AchievementManager.h"
|
|
#include "Core/Boot/Boot.h"
|
|
#include "Core/Config/MainSettings.h"
|
|
#include "Core/Config/SYSCONFSettings.h"
|
|
#include "Core/ConfigLoaders/BaseConfigLoader.h"
|
|
#include "Core/ConfigLoaders/NetPlayConfigLoader.h"
|
|
#include "Core/ConfigManager.h"
|
|
#include "Core/Core.h"
|
|
#include "Core/HW/EXI/EXI.h"
|
|
#include "Core/HW/SI/SI.h"
|
|
#include "Core/HW/SI/SI_Device.h"
|
|
#include "Core/HW/Sram.h"
|
|
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
|
#include "Core/Movie.h"
|
|
#include "Core/NetPlayProto.h"
|
|
#include "Core/PowerPC/PowerPC.h"
|
|
#include "Core/System.h"
|
|
#include "Core/WiiRoot.h"
|
|
|
|
#include "DiscIO/Enums.h"
|
|
|
|
#include "VideoCommon/VideoBackendBase.h"
|
|
|
|
namespace BootManager
|
|
{
|
|
// Boot the ISO or file
|
|
bool BootCore(Core::System& system, std::unique_ptr<BootParameters> boot,
|
|
const WindowSystemInfo& wsi)
|
|
{
|
|
if (!boot)
|
|
return false;
|
|
|
|
SConfig& StartUp = SConfig::GetInstance();
|
|
|
|
if (!StartUp.SetPathsAndGameMetadata(system, *boot))
|
|
return false;
|
|
|
|
// Movie settings
|
|
auto& movie = system.GetMovie();
|
|
if (movie.IsPlayingInput() && movie.IsConfigSaved())
|
|
{
|
|
for (ExpansionInterface::Slot slot : ExpansionInterface::MEMCARD_SLOTS)
|
|
{
|
|
if (movie.IsUsingMemcard(slot) && movie.IsStartingFromClearSave() && !system.IsWii())
|
|
{
|
|
const auto raw_path =
|
|
File::GetUserPath(D_GCUSER_IDX) +
|
|
fmt::format("Movie{}.raw", slot == ExpansionInterface::Slot::A ? 'A' : 'B');
|
|
if (File::Exists(raw_path))
|
|
File::Delete(raw_path);
|
|
|
|
const auto movie_path = File::GetUserPath(D_GCUSER_IDX) + "Movie";
|
|
if (File::Exists(movie_path))
|
|
File::DeleteDirRecursively(movie_path);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NetPlay::IsNetPlayRunning())
|
|
{
|
|
const NetPlay::NetSettings* netplay_settings = boot->boot_session_data.GetNetplaySettings();
|
|
if (!netplay_settings)
|
|
return false;
|
|
|
|
Config::AddLayer(ConfigLoaders::GenerateNetPlayConfigLoader(*netplay_settings));
|
|
StartUp.bCopyWiiSaveNetplay = netplay_settings->savedata_load;
|
|
}
|
|
|
|
// Override out-of-region languages/countries to prevent games from crashing or behaving oddly
|
|
if (!Config::Get(Config::MAIN_OVERRIDE_REGION_SETTINGS))
|
|
{
|
|
Config::SetCurrent(
|
|
Config::MAIN_GC_LANGUAGE,
|
|
DiscIO::ToGameCubeLanguage(StartUp.GetLanguageAdjustedForRegion(false, StartUp.m_region)));
|
|
|
|
if (system.IsWii())
|
|
{
|
|
const u32 wii_language =
|
|
static_cast<u32>(StartUp.GetLanguageAdjustedForRegion(true, StartUp.m_region));
|
|
if (wii_language != Config::Get(Config::SYSCONF_LANGUAGE))
|
|
Config::SetCurrent(Config::SYSCONF_LANGUAGE, wii_language);
|
|
|
|
const u8 country_code = static_cast<u8>(Config::Get(Config::SYSCONF_COUNTRY));
|
|
if (StartUp.m_region != DiscIO::SysConfCountryToRegion(country_code))
|
|
{
|
|
switch (StartUp.m_region)
|
|
{
|
|
case DiscIO::Region::NTSC_J:
|
|
Config::SetCurrent(Config::SYSCONF_COUNTRY, 0x01); // Japan
|
|
break;
|
|
case DiscIO::Region::NTSC_U:
|
|
Config::SetCurrent(Config::SYSCONF_COUNTRY, 0x31); // United States
|
|
break;
|
|
case DiscIO::Region::PAL:
|
|
Config::SetCurrent(Config::SYSCONF_COUNTRY, 0x6c); // Switzerland
|
|
break;
|
|
case DiscIO::Region::NTSC_K:
|
|
Config::SetCurrent(Config::SYSCONF_COUNTRY, 0x88); // South Korea
|
|
break;
|
|
case DiscIO::Region::Unknown:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Some NTSC Wii games such as Doc Louis's Punch-Out!! and
|
|
// 1942 (Virtual Console) crash if the PAL60 option is enabled
|
|
if (system.IsWii() && DiscIO::IsNTSC(StartUp.m_region) && Config::Get(Config::SYSCONF_PAL60))
|
|
Config::SetCurrent(Config::SYSCONF_PAL60, false);
|
|
|
|
// Disable loading time emulation for Riivolution-patched games until we have proper emulation.
|
|
if (!boot->riivolution_patches.empty())
|
|
Config::SetCurrent(Config::MAIN_FAST_DISC_SPEED, true);
|
|
|
|
system.Initialize();
|
|
|
|
Core::UpdateWantDeterminism(system, /*initial*/ true);
|
|
|
|
if (system.IsWii())
|
|
{
|
|
Core::InitializeWiiRoot(Core::WantsDeterminism());
|
|
|
|
// Ensure any new settings are written to the SYSCONF
|
|
if (!Core::WantsDeterminism())
|
|
{
|
|
Core::BackupWiiSettings();
|
|
ConfigLoaders::SaveToSYSCONF(Config::LayerType::Meta);
|
|
}
|
|
else
|
|
{
|
|
ConfigLoaders::SaveToSYSCONF(Config::LayerType::Meta, [](const Config::Location& location) {
|
|
return Config::GetActiveLayerForConfig(location) >= Config::LayerType::Movie;
|
|
});
|
|
}
|
|
}
|
|
|
|
AchievementManager::GetInstance().CloseGame();
|
|
|
|
const bool load_ipl = !system.IsWii() && !Config::Get(Config::MAIN_SKIP_IPL) &&
|
|
std::holds_alternative<BootParameters::Disc>(boot->parameters);
|
|
if (load_ipl)
|
|
{
|
|
return Core::Init(
|
|
system,
|
|
std::make_unique<BootParameters>(
|
|
BootParameters::IPL{StartUp.m_region,
|
|
std::move(std::get<BootParameters::Disc>(boot->parameters))},
|
|
std::move(boot->boot_session_data)),
|
|
wsi);
|
|
}
|
|
return Core::Init(system, std::move(boot), wsi);
|
|
}
|
|
|
|
// SYSCONF can be modified during emulation by the user and internally, which makes it
|
|
// a bad idea to just always overwrite it with the settings from the base layer.
|
|
//
|
|
// Conversely, we also shouldn't just accept any changes to SYSCONF, as it may cause
|
|
// temporary settings (from Movie, Netplay, game INIs, etc.) to stick around.
|
|
//
|
|
// To avoid inconveniences in most cases, we accept changes that aren't being overriden by a
|
|
// non-base layer, and restore only the overriden settings.
|
|
static void RestoreSYSCONF()
|
|
{
|
|
// This layer contains the new SYSCONF settings (including any temporary settings).
|
|
Config::Layer temp_layer(Config::LayerType::Base);
|
|
// Use a separate loader so the temp layer doesn't automatically save
|
|
ConfigLoaders::GenerateBaseConfigLoader()->Load(&temp_layer);
|
|
|
|
for (const auto& setting : Config::SYSCONF_SETTINGS)
|
|
{
|
|
std::visit(
|
|
[&](auto* info) {
|
|
// If this setting was overridden, then we copy the base layer value back to the SYSCONF.
|
|
// Otherwise we leave the new value in the SYSCONF.
|
|
if (Config::GetActiveLayerForConfig(*info) == Config::LayerType::Base)
|
|
Config::SetBase(*info, temp_layer.Get(*info));
|
|
},
|
|
setting.config_info);
|
|
}
|
|
// Save the SYSCONF.
|
|
Config::GetLayer(Config::LayerType::Base)->Save();
|
|
}
|
|
|
|
void RestoreConfig()
|
|
{
|
|
Core::ShutdownWiiRoot();
|
|
|
|
if (!Core::WiiRootIsTemporary())
|
|
{
|
|
Core::RestoreWiiSettings(Core::RestoreReason::EmulationEnd);
|
|
RestoreSYSCONF();
|
|
}
|
|
|
|
Config::ClearCurrentRunLayer();
|
|
Config::RemoveLayer(Config::LayerType::Movie);
|
|
Config::RemoveLayer(Config::LayerType::Netplay);
|
|
Config::RemoveLayer(Config::LayerType::GlobalGame);
|
|
Config::RemoveLayer(Config::LayerType::LocalGame);
|
|
SConfig::GetInstance().ResetRunningGameMetadata();
|
|
}
|
|
|
|
} // namespace BootManager
|