mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-02-19 06:47:43 -07:00
The functions SaveToSYSCONF and LoadFromSYSCONF contain checks for whether emulation is running. The intent of this is that when we're emulating a Wii, the emulated system may write to SYSCONF whenever it likes and does not expect anything else to write to SYSCONF, so the host code shouldn't access SYSCONF while emulation is ongoing. However, Core::IsRunning is an imperfect proxy for whether we've handed over control of SYSCONF to the emulated system yet, as the actual handover happens at a slightly different point in time than when the emulation state is changed. This usually isn't a problem, but in theory it could be a determinism problem if a setting is changed right as emulation is starting, or it could cause the emulated software to briefly misbehave if a setting is changed right as emulation is stopping. Things got worse in72cf2bdb87when I replaced the Core::IsRunning calls with !Core::IsUninitialized. With IsRunning, there was be a period of time where SYSCONF should have been protected but wasn't. With !IsUninitialized, there was a period of time where SYSCONF shouldn't have been protected but was, and crucially, this period of time included the moments where we do setup and teardown of the emulated NAND, which broke transferring SYSCONF settings between the host and the guest.72cf2bdb87was reverted because of this. This commit adds a flag that we explicitly flip when control is handed over to or from the emulated system. This protects the SYSCONF file for exactly as long as is needed.
203 lines
6.6 KiB
C++
203 lines
6.6 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 <fmt/format.h>
|
|
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/Config/Config.h"
|
|
#include "Common/FileUtil.h"
|
|
|
|
#include "Core/AchievementManager.h"
|
|
#include "Core/Boot/Boot.h"
|
|
#include "Core/Config/MainSettings.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/Movie.h"
|
|
#include "Core/NetPlayProto.h"
|
|
#include "Core/System.h"
|
|
#include "Core/WiiRoot.h"
|
|
|
|
#include "DiscIO/Enums.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);
|
|
|
|
ConfigLoaders::TransferSYSCONFControlToGuest();
|
|
|
|
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,
|
|
ConfigLoaders::SkipIfControlledByGuest::No);
|
|
}
|
|
else
|
|
{
|
|
ConfigLoaders::SaveToSYSCONF(
|
|
Config::LayerType::Meta, ConfigLoaders::SkipIfControlledByGuest::No,
|
|
[](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);
|
|
}
|
|
|
|
void RestoreConfig()
|
|
{
|
|
Core::ShutdownWiiRoot();
|
|
|
|
if (Core::WiiRootIsTemporary())
|
|
{
|
|
ConfigLoaders::TransferSYSCONFControlFromGuest(ConfigLoaders::WriteBackChangedValues::No);
|
|
}
|
|
else
|
|
{
|
|
Core::RestoreWiiSettings(Core::RestoreReason::EmulationEnd);
|
|
ConfigLoaders::TransferSYSCONFControlFromGuest(ConfigLoaders::WriteBackChangedValues::Yes);
|
|
}
|
|
|
|
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
|