mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 06:15:38 +00:00
CDROM: Revamp/improve preload image procedure
This commit is contained in:
parent
8d7fdae683
commit
a1edddc59d
|
@ -1,9 +1,11 @@
|
||||||
#include "cdrom.h"
|
#include "cdrom.h"
|
||||||
#include "common/align.h"
|
#include "common/align.h"
|
||||||
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
#include "host_interface_progress_callback.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "interrupt_controller.h"
|
#include "interrupt_controller.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -398,6 +400,30 @@ std::unique_ptr<CDImage> CDROM::RemoveMedia(bool force /* = false */)
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CDROM::PrecacheMedia()
|
||||||
|
{
|
||||||
|
if (!m_reader.HasMedia())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (m_reader.GetMedia()->HasSubImages() && m_reader.GetMedia()->GetSubImageCount() > 1)
|
||||||
|
{
|
||||||
|
Host::AddFormattedOSDMessage(
|
||||||
|
15.0f, Host::TranslateString("OSDMessage", "CD image preloading not available for multi-disc image '%s'"),
|
||||||
|
FileSystem::GetDisplayNameFromPath(m_reader.GetMedia()->GetFileName()).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HostInterfaceProgressCallback callback;
|
||||||
|
if (!m_reader.Precache(&callback))
|
||||||
|
{
|
||||||
|
Host::AddOSDMessage(Host::TranslateStdString("OSDMessage", "Precaching CD image failed, it may be unreliable."),
|
||||||
|
15.0f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void CDROM::SetReadaheadSectors(u32 readahead_sectors)
|
void CDROM::SetReadaheadSectors(u32 readahead_sectors)
|
||||||
{
|
{
|
||||||
const bool want_thread = (readahead_sectors > 0);
|
const bool want_thread = (readahead_sectors > 0);
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class ProgressCallback;
|
||||||
|
|
||||||
class StateWrapper;
|
class StateWrapper;
|
||||||
class TimingEvent;
|
class TimingEvent;
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ public:
|
||||||
|
|
||||||
void InsertMedia(std::unique_ptr<CDImage> media);
|
void InsertMedia(std::unique_ptr<CDImage> media);
|
||||||
std::unique_ptr<CDImage> RemoveMedia(bool force = false);
|
std::unique_ptr<CDImage> RemoveMedia(bool force = false);
|
||||||
|
bool PrecacheMedia();
|
||||||
|
|
||||||
void CPUClockChanged();
|
void CPUClockChanged();
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,45 @@ std::unique_ptr<CDImage> CDROMAsyncReader::RemoveMedia()
|
||||||
return std::move(m_media);
|
return std::move(m_media);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CDROMAsyncReader::Precache(ProgressCallback* callback)
|
||||||
|
{
|
||||||
|
WaitForIdle();
|
||||||
|
|
||||||
|
std::unique_lock lock(m_mutex);
|
||||||
|
if (!m_media)
|
||||||
|
return false;
|
||||||
|
else if (m_media->IsPrecached())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
EmptyBuffers();
|
||||||
|
|
||||||
|
const CDImage::PrecacheResult res = m_media->Precache(callback);
|
||||||
|
if (res == CDImage::PrecacheResult::Unsupported)
|
||||||
|
{
|
||||||
|
// fall back to copy precaching
|
||||||
|
std::unique_ptr<CDImage> memory_image = CDImage::CreateMemoryImage(m_media.get(), callback);
|
||||||
|
if (memory_image)
|
||||||
|
{
|
||||||
|
const CDImage::LBA lba = m_media->GetPositionOnDisc();
|
||||||
|
if (!memory_image->Seek(lba))
|
||||||
|
{
|
||||||
|
Log_ErrorPrintf("Failed to seek to LBA %u in memory image", lba);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_media.reset();
|
||||||
|
m_media = std::move(memory_image);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (res == CDImage::PrecacheResult::Success);
|
||||||
|
}
|
||||||
|
|
||||||
void CDROMAsyncReader::QueueReadSector(CDImage::LBA lba)
|
void CDROMAsyncReader::QueueReadSector(CDImage::LBA lba)
|
||||||
{
|
{
|
||||||
if (!IsUsingThread())
|
if (!IsUsingThread())
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
class ProgressCallback;
|
||||||
|
|
||||||
class CDROMAsyncReader
|
class CDROMAsyncReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -40,6 +42,9 @@ public:
|
||||||
void SetMedia(std::unique_ptr<CDImage> media);
|
void SetMedia(std::unique_ptr<CDImage> media);
|
||||||
std::unique_ptr<CDImage> RemoveMedia();
|
std::unique_ptr<CDImage> RemoveMedia();
|
||||||
|
|
||||||
|
/// Precaches image, either to memory, or using the underlying image precache.
|
||||||
|
bool Precache(ProgressCallback* callback);
|
||||||
|
|
||||||
void QueueReadSector(CDImage::LBA lba);
|
void QueueReadSector(CDImage::LBA lba);
|
||||||
|
|
||||||
bool WaitForReadToComplete();
|
bool WaitForReadToComplete();
|
||||||
|
|
|
@ -89,8 +89,7 @@ static bool LoadEXE(const char* filename);
|
||||||
static std::string GetExecutableNameForImage(ISOReader& iso, bool strip_subdirectories);
|
static std::string GetExecutableNameForImage(ISOReader& iso, bool strip_subdirectories);
|
||||||
|
|
||||||
/// Opens CD image, preloading if needed.
|
/// Opens CD image, preloading if needed.
|
||||||
static std::unique_ptr<CDImage> OpenCDImage(const char* path, Common::Error* error, bool force_preload,
|
static std::unique_ptr<CDImage> OpenCDImage(const char* path, Common::Error* error, bool check_for_patches);
|
||||||
bool check_for_patches);
|
|
||||||
static bool ReadExecutableFromImage(ISOReader& iso, std::string* out_executable_name,
|
static bool ReadExecutableFromImage(ISOReader& iso, std::string* out_executable_name,
|
||||||
std::vector<u8>* out_executable_data);
|
std::vector<u8>* out_executable_data);
|
||||||
static bool ShouldCheckForImagePatches();
|
static bool ShouldCheckForImagePatches();
|
||||||
|
@ -756,42 +755,12 @@ bool System::RecreateGPU(GPURenderer renderer, bool force_recreate_display, bool
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CDImage> System::OpenCDImage(const char* path, Common::Error* error, bool force_preload,
|
std::unique_ptr<CDImage> System::OpenCDImage(const char* path, Common::Error* error, bool check_for_patches)
|
||||||
bool check_for_patches)
|
|
||||||
{
|
{
|
||||||
std::unique_ptr<CDImage> media = CDImage::Open(path, error);
|
std::unique_ptr<CDImage> media = CDImage::Open(path, error);
|
||||||
if (!media)
|
if (!media)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (force_preload || g_settings.cdrom_load_image_to_ram)
|
|
||||||
{
|
|
||||||
if (media->HasSubImages() && media->GetSubImageCount() > 1)
|
|
||||||
{
|
|
||||||
Host::AddFormattedOSDMessage(
|
|
||||||
15.0f, Host::TranslateString("OSDMessage", "CD image preloading not available for multi-disc image '%s'"),
|
|
||||||
FileSystem::GetDisplayNameFromPath(media->GetFileName()).c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HostInterfaceProgressCallback callback;
|
|
||||||
const CDImage::PrecacheResult res = media->Precache(&callback);
|
|
||||||
if (res == CDImage::PrecacheResult::Unsupported)
|
|
||||||
{
|
|
||||||
// fall back to copy precaching
|
|
||||||
std::unique_ptr<CDImage> 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)
|
|
||||||
{
|
|
||||||
Host::AddOSDMessage(Host::TranslateStdString("OSDMessage", "Precaching CD image failed, it may be unreliable."),
|
|
||||||
15.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_for_patches)
|
if (check_for_patches)
|
||||||
{
|
{
|
||||||
const std::string ppf_filename(
|
const std::string ppf_filename(
|
||||||
|
@ -804,7 +773,7 @@ std::unique_ptr<CDImage> System::OpenCDImage(const char* path, Common::Error* er
|
||||||
Host::AddFormattedOSDMessage(
|
Host::AddFormattedOSDMessage(
|
||||||
30.0f, Host::TranslateString("OSDMessage", "Failed to apply ppf patch from '%s', using unpatched image."),
|
30.0f, Host::TranslateString("OSDMessage", "Failed to apply ppf patch from '%s', using unpatched image."),
|
||||||
ppf_filename.c_str());
|
ppf_filename.c_str());
|
||||||
return OpenCDImage(path, error, force_preload, false);
|
return OpenCDImage(path, error, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1041,9 +1010,9 @@ bool System::SaveState(const char* filename, bool backup_existing_save)
|
||||||
|
|
||||||
bool System::BootSystem(SystemBootParameters parameters)
|
bool System::BootSystem(SystemBootParameters parameters)
|
||||||
{
|
{
|
||||||
if (parameters.filename.empty() && !parameters.save_state.empty())
|
if (!parameters.save_state.empty())
|
||||||
{
|
{
|
||||||
// loading a state without media, so pull the media path from the save state to avoid a double change
|
// loading a state, so pull the media path from the save state to avoid a double change
|
||||||
parameters.filename = GetMediaPathFromSaveState(parameters.save_state.c_str());
|
parameters.filename = GetMediaPathFromSaveState(parameters.save_state.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1080,8 +1049,7 @@ bool System::BootSystem(SystemBootParameters parameters)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log_InfoPrintf("Loading CD image '%s'...", parameters.filename.c_str());
|
Log_InfoPrintf("Loading CD image '%s'...", parameters.filename.c_str());
|
||||||
media =
|
media = OpenCDImage(parameters.filename.c_str(), &error, ShouldCheckForImagePatches());
|
||||||
OpenCDImage(parameters.filename.c_str(), &error, parameters.load_image_to_ram, ShouldCheckForImagePatches());
|
|
||||||
if (!media)
|
if (!media)
|
||||||
{
|
{
|
||||||
Host::ReportErrorAsync("Error", fmt::format("Failed to load CD image '{}': {}",
|
Host::ReportErrorAsync("Error", fmt::format("Failed to load CD image '{}': {}",
|
||||||
|
@ -1243,6 +1211,9 @@ bool System::BootSystem(SystemBootParameters parameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parameters.load_image_to_ram || g_settings.cdrom_load_image_to_ram)
|
||||||
|
g_cdrom.PrecacheMedia();
|
||||||
|
|
||||||
ResetPerformanceCounters();
|
ResetPerformanceCounters();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1703,6 +1674,8 @@ std::string System::GetMediaPathFromSaveState(const char* path)
|
||||||
|
|
||||||
bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool update_display)
|
bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool update_display)
|
||||||
{
|
{
|
||||||
|
Assert(IsValid());
|
||||||
|
|
||||||
SAVE_STATE_HEADER header;
|
SAVE_STATE_HEADER header;
|
||||||
if (!state->Read2(&header, sizeof(header)))
|
if (!state->Read2(&header, sizeof(header)))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1748,7 +1721,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
media = OpenCDImage(media_filename.c_str(), &error, false, ShouldCheckForImagePatches());
|
media = OpenCDImage(media_filename.c_str(), &error, ShouldCheckForImagePatches());
|
||||||
if (!media)
|
if (!media)
|
||||||
{
|
{
|
||||||
if (old_media)
|
if (old_media)
|
||||||
|
@ -1794,32 +1767,22 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u
|
||||||
|
|
||||||
ClearMemorySaveStates();
|
ClearMemorySaveStates();
|
||||||
|
|
||||||
if (s_state == State::Starting)
|
g_cdrom.Reset();
|
||||||
|
if (media)
|
||||||
{
|
{
|
||||||
if (!Initialize(force_software_renderer))
|
g_cdrom.InsertMedia(std::move(media));
|
||||||
return false;
|
if (g_settings.cdrom_load_image_to_ram)
|
||||||
|
g_cdrom.PrecacheMedia();
|
||||||
if (media)
|
|
||||||
g_cdrom.InsertMedia(std::move(media));
|
|
||||||
|
|
||||||
UpdateControllers();
|
|
||||||
UpdateMemoryCardTypes();
|
|
||||||
UpdateMultitaps();
|
|
||||||
InternalReset();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_cdrom.Reset();
|
g_cdrom.RemoveMedia();
|
||||||
if (media)
|
|
||||||
g_cdrom.InsertMedia(std::move(media));
|
|
||||||
else
|
|
||||||
g_cdrom.RemoveMedia();
|
|
||||||
|
|
||||||
// ensure the correct card is loaded
|
|
||||||
if (g_settings.HasAnyPerGameMemoryCards())
|
|
||||||
UpdatePerGameMemoryCards();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure the correct card is loaded
|
||||||
|
if (g_settings.HasAnyPerGameMemoryCards())
|
||||||
|
UpdatePerGameMemoryCards();
|
||||||
|
|
||||||
if (header.data_compression_type != 0)
|
if (header.data_compression_type != 0)
|
||||||
{
|
{
|
||||||
Host::ReportFormattedErrorAsync("Error", "Unknown save state compression type %u", header.data_compression_type);
|
Host::ReportFormattedErrorAsync("Error", "Unknown save state compression type %u", header.data_compression_type);
|
||||||
|
@ -2810,7 +2773,7 @@ std::string System::GetMediaFileName()
|
||||||
bool System::InsertMedia(const char* path)
|
bool System::InsertMedia(const char* path)
|
||||||
{
|
{
|
||||||
Common::Error error;
|
Common::Error error;
|
||||||
std::unique_ptr<CDImage> image = OpenCDImage(path, &error, false, ShouldCheckForImagePatches());
|
std::unique_ptr<CDImage> image = OpenCDImage(path, &error, ShouldCheckForImagePatches());
|
||||||
if (!image)
|
if (!image)
|
||||||
{
|
{
|
||||||
Host::AddFormattedOSDMessage(10.0f, Host::TranslateString("OSDMessage", "Failed to open disc image '%s': %s."),
|
Host::AddFormattedOSDMessage(10.0f, Host::TranslateString("OSDMessage", "Failed to open disc image '%s': %s."),
|
||||||
|
@ -2822,6 +2785,9 @@ bool System::InsertMedia(const char* path)
|
||||||
g_cdrom.InsertMedia(std::move(image));
|
g_cdrom.InsertMedia(std::move(image));
|
||||||
Log_InfoPrintf("Inserted media from %s (%s, %s)", s_running_game_path.c_str(), s_running_game_code.c_str(),
|
Log_InfoPrintf("Inserted media from %s (%s, %s)", s_running_game_path.c_str(), s_running_game_code.c_str(),
|
||||||
s_running_game_title.c_str());
|
s_running_game_title.c_str());
|
||||||
|
if (g_settings.cdrom_load_image_to_ram)
|
||||||
|
g_cdrom.PrecacheMedia();
|
||||||
|
|
||||||
Host::AddFormattedOSDMessage(10.0f, Host::TranslateString("OSDMessage", "Inserted disc '%s' (%s)."),
|
Host::AddFormattedOSDMessage(10.0f, Host::TranslateString("OSDMessage", "Inserted disc '%s' (%s)."),
|
||||||
s_running_game_title.c_str(), s_running_game_code.c_str());
|
s_running_game_title.c_str(), s_running_game_code.c_str());
|
||||||
|
|
||||||
|
|
|
@ -330,6 +330,11 @@ CDImage::PrecacheResult CDImage::Precache(ProgressCallback* progress /*= Progres
|
||||||
return PrecacheResult::Unsupported;
|
return PrecacheResult::Unsupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CDImage::IsPrecached() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CDImage::ClearTOC()
|
void CDImage::ClearTOC()
|
||||||
{
|
{
|
||||||
m_lba_count = 0;
|
m_lba_count = 0;
|
||||||
|
|
|
@ -303,6 +303,7 @@ public:
|
||||||
|
|
||||||
// Returns true if the source supports precaching, which may be more optimal than an in-memory copy.
|
// Returns true if the source supports precaching, which may be more optimal than an in-memory copy.
|
||||||
virtual PrecacheResult Precache(ProgressCallback* progress = ProgressCallback::NullProgressCallback);
|
virtual PrecacheResult Precache(ProgressCallback* progress = ProgressCallback::NullProgressCallback);
|
||||||
|
virtual bool IsPrecached() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ClearTOC();
|
void ClearTOC();
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
|
#include "fmt/format.h"
|
||||||
#include "libchdr/chd.h"
|
#include "libchdr/chd.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
@ -53,6 +54,7 @@ public:
|
||||||
bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override;
|
bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override;
|
||||||
bool HasNonStandardSubchannel() const override;
|
bool HasNonStandardSubchannel() const override;
|
||||||
PrecacheResult Precache(ProgressCallback* progress) override;
|
PrecacheResult Precache(ProgressCallback* progress) override;
|
||||||
|
bool IsPrecached() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index) override;
|
bool ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index) override;
|
||||||
|
@ -73,6 +75,7 @@ private:
|
||||||
|
|
||||||
std::vector<u8> m_hunk_buffer;
|
std::vector<u8> m_hunk_buffer;
|
||||||
u32 m_current_hunk_index = static_cast<u32>(-1);
|
u32 m_current_hunk_index = static_cast<u32>(-1);
|
||||||
|
bool m_precached = false;
|
||||||
|
|
||||||
CDSubChannelReplacement m_sbi;
|
CDSubChannelReplacement m_sbi;
|
||||||
};
|
};
|
||||||
|
@ -303,16 +306,27 @@ bool CDImageCHD::HasNonStandardSubchannel() const
|
||||||
|
|
||||||
CDImage::PrecacheResult CDImageCHD::Precache(ProgressCallback* progress)
|
CDImage::PrecacheResult CDImageCHD::Precache(ProgressCallback* progress)
|
||||||
{
|
{
|
||||||
const std::string_view title(FileSystem::GetDisplayNameFromPath(m_filename));
|
if (m_precached)
|
||||||
progress->SetFormattedStatusText("Precaching %.*s...", static_cast<int>(title.size()), title.data());
|
return CDImage::PrecacheResult::Success;
|
||||||
|
|
||||||
|
progress->SetStatusText(fmt::format("Precaching {}...", FileSystem::GetDisplayNameFromPath(m_filename)).c_str());
|
||||||
progress->SetProgressRange(100);
|
progress->SetProgressRange(100);
|
||||||
|
|
||||||
auto callback = [](size_t pos, size_t total, void* param) {
|
auto callback = [](size_t pos, size_t total, void* param) {
|
||||||
const u32 percent = static_cast<u32>((pos * 100) / total);
|
const u32 percent = static_cast<u32>((pos * 100) / total);
|
||||||
static_cast<ProgressCallback*>(param)->SetProgressValue(std::min<u32>(percent, 100));
|
static_cast<ProgressCallback*>(param)->SetProgressValue(std::min<u32>(percent, 100));
|
||||||
};
|
};
|
||||||
return (chd_precache_progress(m_chd, callback, progress) == CHDERR_NONE) ? CDImage::PrecacheResult::Success :
|
|
||||||
CDImage::PrecacheResult::ReadError;
|
if (chd_precache_progress(m_chd, callback, progress) != CHDERR_NONE)
|
||||||
|
return CDImage::PrecacheResult::ReadError;
|
||||||
|
|
||||||
|
m_precached = true;
|
||||||
|
return CDImage::PrecacheResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDImageCHD::IsPrecached() const
|
||||||
|
{
|
||||||
|
return m_precached;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There's probably a more efficient way of doing this with vectorization...
|
// There's probably a more efficient way of doing this with vectorization...
|
||||||
|
|
|
@ -19,6 +19,8 @@ public:
|
||||||
bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override;
|
bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override;
|
||||||
bool HasNonStandardSubchannel() const override;
|
bool HasNonStandardSubchannel() const override;
|
||||||
|
|
||||||
|
bool IsPrecached() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index) override;
|
bool ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index) override;
|
||||||
|
|
||||||
|
@ -128,6 +130,11 @@ bool CDImageMemory::HasNonStandardSubchannel() const
|
||||||
return (m_sbi.GetReplacementSectorCount() > 0);
|
return (m_sbi.GetReplacementSectorCount() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CDImageMemory::IsPrecached() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CDImageMemory::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index)
|
bool CDImageMemory::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index)
|
||||||
{
|
{
|
||||||
DebugAssert(index.file_index == 0);
|
DebugAssert(index.file_index == 0);
|
||||||
|
|
Loading…
Reference in a new issue