From 9ab64ecdb3fb02bb95fbf492496b8545a8d656e1 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 3 Apr 2022 20:55:27 +1000 Subject: [PATCH] CDImage: Add Precache() method --- src/common/cd_image.cpp | 5 +++++ src/common/cd_image.h | 10 ++++++++++ src/core/system.cpp | 21 ++++++++++++++++----- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/common/cd_image.cpp b/src/common/cd_image.cpp index 1d384e815..1efd3ce9d 100644 --- a/src/common/cd_image.cpp +++ b/src/common/cd_image.cpp @@ -324,6 +324,11 @@ std::string CDImage::GetSubImageMetadata(u32 index, const std::string_view& type return {}; } +CDImage::PrecacheResult CDImage::Precache(ProgressCallback* progress /*= ProgressCallback::NullProgressCallback*/) +{ + return PrecacheResult::Unsupported; +} + void CDImage::ClearTOC() { m_lba_count = 0; diff --git a/src/common/cd_image.h b/src/common/cd_image.h index 03d88b27d..33e221cff 100644 --- a/src/common/cd_image.h +++ b/src/common/cd_image.h @@ -57,6 +57,13 @@ public: Mode2Raw // 2352 bytes per sector }; + enum class PrecacheResult : u8 + { + Unsupported, + ReadError, + Success, + }; + struct SectorHeader { u8 minute; @@ -294,6 +301,9 @@ public: // Retrieve sub-image metadata. virtual std::string GetSubImageMetadata(u32 index, const std::string_view& type) const; + // Returns true if the source supports precaching, which may be more optimal than an in-memory copy. + virtual PrecacheResult Precache(ProgressCallback* progress = ProgressCallback::NullProgressCallback); + protected: void ClearTOC(); void CopyTOC(const CDImage* image); diff --git a/src/core/system.cpp b/src/core/system.cpp index 91de0eecb..d5dbc1286 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -683,11 +683,22 @@ std::unique_ptr OpenCDImage(const char* path, Common::Error* error, boo else { HostInterfaceProgressCallback callback; - std::unique_ptr memory_image = CDImage::CreateMemoryImage(media.get(), &callback); - if (memory_image) - media = std::move(memory_image); - else - Log_WarningPrintf("Failed to preload image '%s' to RAM", path); + const CDImage::PrecacheResult res = media->Precache(&callback); + if (res == CDImage::PrecacheResult::Unsupported) + { + // fall back to copy precaching + std::unique_ptr memory_image = CDImage::CreateMemoryImage(media.get(), &callback); + if (memory_image) + media = std::move(memory_image); + else + Log_WarningPrintf("Failed to preload image '%s' to RAM", path); + } + else if (res != CDImage::PrecacheResult::Success) + { + g_host_interface->AddOSDMessage( + g_host_interface->TranslateStdString("OSDMessage", "Precaching CD image failed, it may be unreliable."), + 15.0f); + } } }