diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 755ed0427a3..236cea81b9c 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -240,7 +240,7 @@ std::unique_ptr BootParameters::GenerateFromFile(std::vector disc = DiscIO::CreateDisc(path); + std::unique_ptr disc = DiscIO::CreateDiscForCore(path); if (disc) { return std::make_unique(Disc{std::move(path), std::move(disc), paths}, @@ -469,7 +469,7 @@ static void SetDefaultDisc(DVD::DVDInterface& dvd_interface) { const std::string default_iso = Config::Get(Config::MAIN_DEFAULT_ISO); if (!default_iso.empty()) - SetDisc(dvd_interface, DiscIO::CreateDisc(default_iso)); + SetDisc(dvd_interface, DiscIO::CreateDiscForCore(default_iso)); } static void CopyDefaultExceptionHandlers(Core::System& system) @@ -629,7 +629,7 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard, if (ipl.disc) { NOTICE_LOG_FMT(BOOT, "Inserting disc: {}", ipl.disc->path); - SetDisc(system.GetDVDInterface(), DiscIO::CreateDisc(ipl.disc->path), + SetDisc(system.GetDVDInterface(), DiscIO::CreateDiscForCore(ipl.disc->path), ipl.disc->auto_disc_change_paths); } else diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index b06fb5b4963..4a22728a842 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -58,6 +58,7 @@ constexpr bool DEFAULT_CPU_THREAD = true; constexpr bool DEFAULT_CPU_THREAD = false; #endif const Info MAIN_CPU_THREAD{{System::Main, "Core", "CPUThread"}, DEFAULT_CPU_THREAD}; +const Info MAIN_LOAD_GAME_INTO_MEMORY{{System::Main, "Core", "LoadGameIntoMemory"}, false}; const Info MAIN_SYNC_ON_SKIP_IDLE{{System::Main, "Core", "SyncOnSkipIdle"}, true}; const Info MAIN_DEFAULT_ISO{{System::Main, "Core", "DefaultISO"}, ""}; const Info MAIN_ENABLE_CHEATS{{System::Main, "Core", "EnableCheats"}, false}; diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index cc64c80d69c..17689f7ecac 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -68,6 +68,7 @@ extern const Info MAIN_CORRECT_TIME_DRIFT; extern const Info MAIN_RUSH_FRAME_PRESENTATION; extern const Info MAIN_SMOOTH_EARLY_PRESENTATION; extern const Info MAIN_CPU_THREAD; +extern const Info MAIN_LOAD_GAME_INTO_MEMORY; extern const Info MAIN_SYNC_ON_SKIP_IDLE; extern const Info MAIN_DEFAULT_ISO; extern const Info MAIN_ENABLE_CHEATS; diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index 410f5763a55..49cafccb70a 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -428,7 +428,8 @@ void DVDInterface::EjectDiscCallback(Core::System& system, u64 userdata, s64 cyc void DVDInterface::InsertDiscCallback(Core::System& system, u64 userdata, s64 cyclesLate) { auto& di = system.GetDVDInterface(); - std::unique_ptr new_disc = DiscIO::CreateDisc(di.m_disc_path_to_insert); + std::unique_ptr new_disc = + DiscIO::CreateDiscForCore(di.m_disc_path_to_insert); if (new_disc) di.SetDisc(std::move(new_disc), {}); diff --git a/Source/Core/DiscIO/Volume.cpp b/Source/Core/DiscIO/Volume.cpp index b6d84254f01..7e5dcc7976c 100644 --- a/Source/Core/DiscIO/Volume.cpp +++ b/Source/Core/DiscIO/Volume.cpp @@ -3,7 +3,7 @@ #include "DiscIO/Volume.h" -#include +#include #include #include #include @@ -16,8 +16,11 @@ #include "Common/Crypto/SHA1.h" #include "Common/StringUtil.h" +#include "Core/Config/MainSettings.h" #include "Core/IOS/ES/Formats.h" + #include "DiscIO/Blob.h" +#include "DiscIO/CachedBlob.h" #include "DiscIO/DiscUtils.h" #include "DiscIO/Enums.h" #include "DiscIO/VolumeDisc.h" @@ -84,16 +87,21 @@ std::map Volume::ReadWiiNames(const std::vector return names; } -static std::unique_ptr TryCreateDisc(std::unique_ptr& reader) +template +static std::unique_ptr TryCreateDisc(std::unique_ptr reader, + const T& reader_adapter_factory = {}) { if (!reader) return nullptr; + // `reader_adapter_factory` is used *after* successful magic word read. + // This prevents `CachedBlobReader` from showing warnings when failing to scrub a .dol file. + if (reader->ReadSwapped(0x18) == WII_DISC_MAGIC) - return std::make_unique(std::move(reader)); + return std::make_unique(reader_adapter_factory(std::move(reader))); if (reader->ReadSwapped(0x1C) == GAMECUBE_DISC_MAGIC) - return std::make_unique(std::move(reader)); + return std::make_unique(reader_adapter_factory(std::move(reader))); // No known magic words found return nullptr; @@ -101,7 +109,7 @@ static std::unique_ptr TryCreateDisc(std::unique_ptr& re std::unique_ptr CreateDisc(std::unique_ptr reader) { - return TryCreateDisc(reader); + return TryCreateDisc(std::move(reader)); } std::unique_ptr CreateDisc(const std::string& path) @@ -109,7 +117,15 @@ std::unique_ptr CreateDisc(const std::string& path) return CreateDisc(CreateBlobReader(path)); } -static std::unique_ptr TryCreateWAD(std::unique_ptr& reader) +std::unique_ptr CreateDiscForCore(const std::string& path) +{ + if (Config::Get(Config::MAIN_LOAD_GAME_INTO_MEMORY)) + return TryCreateDisc(CreateBlobReader(path), CreateScrubbingCachedBlobReader); + + return CreateDisc(path); +} + +static std::unique_ptr TryCreateWAD(std::unique_ptr reader) { if (!reader) return nullptr; @@ -126,7 +142,7 @@ static std::unique_ptr TryCreateWAD(std::unique_ptr& read std::unique_ptr CreateWAD(std::unique_ptr reader) { - return TryCreateWAD(reader); + return TryCreateWAD(std::move(reader)); } std::unique_ptr CreateWAD(const std::string& path) @@ -136,11 +152,11 @@ std::unique_ptr CreateWAD(const std::string& path) std::unique_ptr CreateVolume(std::unique_ptr reader) { - std::unique_ptr disc = TryCreateDisc(reader); + std::unique_ptr disc = TryCreateDisc(std::move(reader)); if (disc) return disc; - std::unique_ptr wad = TryCreateWAD(reader); + std::unique_ptr wad = TryCreateWAD(std::move(reader)); if (wad) return wad; diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index a7273b0f0eb..3f80cd2e3dd 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -176,6 +176,9 @@ protected: std::unique_ptr CreateDisc(std::unique_ptr reader); std::unique_ptr CreateDisc(const std::string& path); +// This version enables caching when the "Load Games into Memory" setting is enabled. +std::unique_ptr CreateDiscForCore(const std::string& path); + std::unique_ptr CreateWAD(std::unique_ptr reader); std::unique_ptr CreateWAD(const std::string& path); std::unique_ptr CreateVolume(std::unique_ptr reader); diff --git a/Source/Core/DolphinQt/Settings/GeneralPane.cpp b/Source/Core/DolphinQt/Settings/GeneralPane.cpp index 93e3d0d9c82..661f5f13b23 100644 --- a/Source/Core/DolphinQt/Settings/GeneralPane.cpp +++ b/Source/Core/DolphinQt/Settings/GeneralPane.cpp @@ -90,6 +90,7 @@ void GeneralPane::OnEmulationStateChanged(Core::State state) m_checkbox_dualcore->setEnabled(!running); m_checkbox_cheats->setEnabled(!running); + m_checkbox_load_games_into_memory->setEnabled(!running); m_checkbox_override_region_settings->setEnabled(!running); #ifdef USE_DISCORD_PRESENCE m_checkbox_discord_presence->setEnabled(!running); @@ -147,6 +148,15 @@ void GeneralPane::CreateBasic() m_checkbox_cheats = new ConfigBool(tr("Enable Cheats"), Config::MAIN_ENABLE_CHEATS); basic_group_layout->addWidget(m_checkbox_cheats); + m_checkbox_load_games_into_memory = + new ConfigBool(tr("Load Whole Game Into Memory"), Config::MAIN_LOAD_GAME_INTO_MEMORY); + basic_group_layout->addWidget(m_checkbox_load_games_into_memory); + m_checkbox_load_games_into_memory->SetDescription( + tr("Loads the running game into memory in the background." + "

This may improve performance with slow or high-latency storage." + "
System memory requirements will be much higher with this setting enabled." + "

If unsure, leave this unchecked.")); + m_checkbox_override_region_settings = new ConfigBool(tr("Allow Mismatched Region Settings"), Config::MAIN_OVERRIDE_REGION_SETTINGS); basic_group_layout->addWidget(m_checkbox_override_region_settings); diff --git a/Source/Core/DolphinQt/Settings/GeneralPane.h b/Source/Core/DolphinQt/Settings/GeneralPane.h index 17d80f7c385..b482172b095 100644 --- a/Source/Core/DolphinQt/Settings/GeneralPane.h +++ b/Source/Core/DolphinQt/Settings/GeneralPane.h @@ -48,6 +48,7 @@ private: ToolTipComboBox* m_combobox_fallback_region; ConfigBool* m_checkbox_dualcore; ConfigBool* m_checkbox_cheats; + ConfigBool* m_checkbox_load_games_into_memory; ConfigBool* m_checkbox_override_region_settings; ConfigBool* m_checkbox_auto_disc_change; #ifdef USE_DISCORD_PRESENCE