diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index 9b58f580e1..4dbe7a2f9d 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -45,6 +45,7 @@ #include "Core/Movie.h" #include "Core/NetPlayProto.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/WiiRoot.h" #include "DiscIO/Enums.h" @@ -439,7 +440,10 @@ bool BootCore(std::unique_ptr boot, const WindowSystemInfo& wsi) // Ensure any new settings are written to the SYSCONF if (StartUp.bWii) + { + Core::BackupWiiSettings(); ConfigLoaders::SaveToSYSCONF(Config::LayerType::Meta); + } const bool load_ipl = !StartUp.bWii && !StartUp.bHLE_BS2 && std::holds_alternative(boot->parameters); @@ -487,6 +491,7 @@ static void RestoreSYSCONF() void RestoreConfig() { + Core::RestoreWiiSettings(Core::RestoreReason::EmulationEnd); RestoreSYSCONF(); Config::ClearCurrentRunLayer(); Config::RemoveLayer(Config::LayerType::Movie); diff --git a/Source/Core/Core/WiiRoot.cpp b/Source/Core/Core/WiiRoot.cpp index c5caf3b7b7..3b7a17ab97 100644 --- a/Source/Core/Core/WiiRoot.cpp +++ b/Source/Core/Core/WiiRoot.cpp @@ -16,6 +16,8 @@ #include "Common/FileUtil.h" #include "Common/Logging/Log.h" #include "Common/NandPaths.h" +#include "Common/StringUtil.h" +#include "Core/CommonTitles.h" #include "Core/ConfigManager.h" #include "Core/HW/WiiSave.h" #include "Core/IOS/ES/ES.h" @@ -32,6 +34,38 @@ namespace FS = IOS::HLE::FS; static std::string s_temp_wii_root; +static bool CopyBackupFile(const std::string& path_from, const std::string& path_to) +{ + if (!File::Exists(path_from)) + return false; + + return File::Copy(path_from, path_to); +} + +static void DeleteBackupFile(const std::string& file_name) +{ + File::Delete(File::GetUserPath(D_BACKUP_IDX) + DIR_SEP + file_name); +} + +static void BackupFile(const std::string& path_in_nand) +{ + const std::string file_name = PathToFileName(path_in_nand); + const std::string original_path = File::GetUserPath(D_WIIROOT_IDX) + DIR_SEP + path_in_nand; + const std::string backup_path = File::GetUserPath(D_BACKUP_IDX) + DIR_SEP + file_name; + + CopyBackupFile(original_path, backup_path); +} + +static void RestoreFile(const std::string& path_in_nand) +{ + const std::string file_name = PathToFileName(path_in_nand); + const std::string original_path = File::GetUserPath(D_WIIROOT_IDX) + DIR_SEP + path_in_nand; + const std::string backup_path = File::GetUserPath(D_BACKUP_IDX) + DIR_SEP + file_name; + + if (CopyBackupFile(backup_path, original_path)) + DeleteBackupFile(file_name); +} + static void CopySave(FS::FileSystem* source, FS::FileSystem* dest, const u64 title_id) { dest->CreateFullPath(IOS::PID_KERNEL, IOS::PID_KERNEL, Common::GetTitleDataPath(title_id) + '/', @@ -173,6 +207,29 @@ void ShutdownWiiRoot() } } +void BackupWiiSettings() +{ + // Back up files which Dolphin can modify at boot, so that we can preserve the original contents. + // For SYSCONF, the backup is only needed in case Dolphin crashes or otherwise exists unexpectedly + // during emulation, since the config system will restore the SYSCONF settings at emulation end. + // For setting.txt, there is no other code that restores the original values for us. + + BackupFile(Common::GetTitleDataPath(Titles::SYSTEM_MENU) + "/" WII_SETTING); + BackupFile("/shared2/sys/SYSCONF"); +} + +void RestoreWiiSettings(RestoreReason reason) +{ + RestoreFile(Common::GetTitleDataPath(Titles::SYSTEM_MENU) + "/" WII_SETTING); + + // We must not restore the SYSCONF backup when ending emulation cleanly, since the user may have + // edited the SYSCONF file in the NAND using the emulated software (e.g. the Wii Menu settings). + if (reason == RestoreReason::CrashRecovery) + RestoreFile("/shared2/sys/SYSCONF"); + else + DeleteBackupFile("SYSCONF"); +} + /// Copy a directory from host_source_path (on the host FS) to nand_target_path on the NAND. /// /// Both paths should not have trailing slashes. To specify the NAND root, use "". diff --git a/Source/Core/Core/WiiRoot.h b/Source/Core/Core/WiiRoot.h index c62aaa103f..7b069d0c07 100644 --- a/Source/Core/Core/WiiRoot.h +++ b/Source/Core/Core/WiiRoot.h @@ -6,9 +6,18 @@ namespace Core { +enum class RestoreReason +{ + EmulationEnd, + CrashRecovery, +}; + void InitializeWiiRoot(bool use_temporary); void ShutdownWiiRoot(); +void BackupWiiSettings(); +void RestoreWiiSettings(RestoreReason reason); + // Initialize or clean up the filesystem contents. void InitializeWiiFileSystemContents(); void CleanUpWiiFileSystemContents(); diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 76ff64ac25..5af9192711 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -31,6 +31,7 @@ #include "Core/HW/Wiimote.h" #include "Core/IOS/IOS.h" #include "Core/IOS/STM/STM.h" +#include "Core/WiiRoot.h" #include "InputCommon/GCAdapter.h" @@ -88,6 +89,8 @@ static void InitCustomPaths() void Init() { + Core::RestoreWiiSettings(Core::RestoreReason::CrashRecovery); + Config::Init(); Config::AddConfigChangedCallback(InitCustomPaths); Config::AddLayer(ConfigLoaders::GenerateBaseConfigLoader());