System: Move overlay checking to common

This commit is contained in:
Connor McLaughlin 2022-08-27 16:52:24 +10:00
parent ea8d779962
commit 3a5bf6d29b
10 changed files with 119 additions and 80 deletions

View File

@ -129,7 +129,7 @@ std::string GameDatabase::GetSerialForPath(const char* path)
if (System::IsLoadableFilename(path) && !System::IsExeFileName(path) && !System::IsPsfFileName(path)) if (System::IsLoadableFilename(path) && !System::IsExeFileName(path) && !System::IsPsfFileName(path))
{ {
std::unique_ptr<CDImage> image(CDImage::Open(path, nullptr)); std::unique_ptr<CDImage> image(CDImage::Open(path, false, nullptr));
if (image) if (image)
ret = GetSerialForDisc(image.get()); ret = GetSerialForDisc(image.get());
} }

View File

@ -269,6 +269,7 @@ void Settings::Load(SettingsInterface& si)
static_cast<u8>(si.GetIntValue("CDROM", "ReadaheadSectors", DEFAULT_CDROM_READAHEAD_SECTORS)); static_cast<u8>(si.GetIntValue("CDROM", "ReadaheadSectors", DEFAULT_CDROM_READAHEAD_SECTORS));
cdrom_region_check = si.GetBoolValue("CDROM", "RegionCheck", false); cdrom_region_check = si.GetBoolValue("CDROM", "RegionCheck", false);
cdrom_load_image_to_ram = si.GetBoolValue("CDROM", "LoadImageToRAM", false); cdrom_load_image_to_ram = si.GetBoolValue("CDROM", "LoadImageToRAM", false);
cdrom_load_image_patches = si.GetBoolValue("CDROM", "LoadImagePatches", false);
cdrom_mute_cd_audio = si.GetBoolValue("CDROM", "MuteCDAudio", false); cdrom_mute_cd_audio = si.GetBoolValue("CDROM", "MuteCDAudio", false);
cdrom_read_speedup = si.GetIntValue("CDROM", "ReadSpeedup", 1); cdrom_read_speedup = si.GetIntValue("CDROM", "ReadSpeedup", 1);
cdrom_seek_speedup = si.GetIntValue("CDROM", "SeekSpeedup", 1); cdrom_seek_speedup = si.GetIntValue("CDROM", "SeekSpeedup", 1);
@ -474,6 +475,7 @@ void Settings::Save(SettingsInterface& si) const
si.SetIntValue("CDROM", "ReadaheadSectors", cdrom_readahead_sectors); si.SetIntValue("CDROM", "ReadaheadSectors", cdrom_readahead_sectors);
si.SetBoolValue("CDROM", "RegionCheck", cdrom_region_check); si.SetBoolValue("CDROM", "RegionCheck", cdrom_region_check);
si.SetBoolValue("CDROM", "LoadImageToRAM", cdrom_load_image_to_ram); si.SetBoolValue("CDROM", "LoadImageToRAM", cdrom_load_image_to_ram);
si.SetBoolValue("CDROM", "LoadImagePatches", cdrom_load_image_patches);
si.SetBoolValue("CDROM", "MuteCDAudio", cdrom_mute_cd_audio); si.SetBoolValue("CDROM", "MuteCDAudio", cdrom_mute_cd_audio);
si.SetIntValue("CDROM", "ReadSpeedup", cdrom_read_speedup); si.SetIntValue("CDROM", "ReadSpeedup", cdrom_read_speedup);
si.SetIntValue("CDROM", "SeekSpeedup", cdrom_seek_speedup); si.SetIntValue("CDROM", "SeekSpeedup", cdrom_seek_speedup);

View File

@ -143,6 +143,7 @@ struct Settings
u8 cdrom_readahead_sectors = DEFAULT_CDROM_READAHEAD_SECTORS; u8 cdrom_readahead_sectors = DEFAULT_CDROM_READAHEAD_SECTORS;
bool cdrom_region_check = false; bool cdrom_region_check = false;
bool cdrom_load_image_to_ram = false; bool cdrom_load_image_to_ram = false;
bool cdrom_load_image_patches = false;
bool cdrom_mute_cd_audio = false; bool cdrom_mute_cd_audio = false;
u32 cdrom_read_speedup = 1; u32 cdrom_read_speedup = 1;
u32 cdrom_seek_speedup = 1; u32 cdrom_seek_speedup = 1;

View File

@ -87,11 +87,8 @@ 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.
static std::unique_ptr<CDImage> OpenCDImage(const char* path, Common::Error* error, 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 void StallCPU(TickCount ticks); static void StallCPU(TickCount ticks);
@ -406,7 +403,7 @@ ConsoleRegion System::GetConsoleRegionForDiscRegion(DiscRegion region)
std::string System::GetGameCodeForPath(const char* image_path, bool fallback_to_hash) std::string System::GetGameCodeForPath(const char* image_path, bool fallback_to_hash)
{ {
std::unique_ptr<CDImage> cdi = CDImage::Open(image_path, nullptr); std::unique_ptr<CDImage> cdi = CDImage::Open(image_path, false, nullptr);
if (!cdi) if (!cdi)
return {}; return {};
@ -694,7 +691,7 @@ std::optional<DiscRegion> System::GetRegionForPath(const char* image_path)
else if (IsPsfFileName(image_path)) else if (IsPsfFileName(image_path))
return GetRegionForPsf(image_path); return GetRegionForPsf(image_path);
std::unique_ptr<CDImage> cdi = CDImage::Open(image_path, nullptr); std::unique_ptr<CDImage> cdi = CDImage::Open(image_path, false, nullptr);
if (!cdi) if (!cdi)
return {}; return {};
@ -753,37 +750,6 @@ 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 check_for_patches)
{
std::unique_ptr<CDImage> media = CDImage::Open(path, error);
if (!media)
return {};
if (check_for_patches)
{
const std::string ppf_filename(
Path::BuildRelativePath(path, Path::ReplaceExtension(FileSystem::GetDisplayNameFromPath(path), "ppf")));
if (FileSystem::FileExists(ppf_filename.c_str()))
{
media = CDImage::OverlayPPFPatch(ppf_filename.c_str(), std::move(media));
if (!media)
{
Host::AddFormattedOSDMessage(
30.0f, Host::TranslateString("OSDMessage", "Failed to apply ppf patch from '%s', using unpatched image."),
ppf_filename.c_str());
return OpenCDImage(path, error, false);
}
}
}
return media;
}
bool System::ShouldCheckForImagePatches()
{
return Host::GetBoolSettingValue("CDROM", "LoadImagePatches", false);
}
void System::LoadSettings(bool display_osd_messages) void System::LoadSettings(bool display_osd_messages)
{ {
std::unique_lock<std::mutex> lock = Host::GetSettingsLock(); std::unique_lock<std::mutex> lock = Host::GetSettingsLock();
@ -1094,7 +1060,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 = OpenCDImage(parameters.filename.c_str(), &error, ShouldCheckForImagePatches()); media = CDImage::Open(parameters.filename.c_str(), g_settings.cdrom_load_image_patches, &error);
if (!media) if (!media)
{ {
Host::ReportErrorAsync("Error", fmt::format("Failed to load CD image '{}': {}", Host::ReportErrorAsync("Error", fmt::format("Failed to load CD image '{}': {}",
@ -1777,7 +1743,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u
} }
else else
{ {
media = OpenCDImage(media_filename.c_str(), &error, ShouldCheckForImagePatches()); media = CDImage::Open(media_filename.c_str(), g_settings.cdrom_load_image_patches, &error);
if (!media) if (!media)
{ {
if (old_media) if (old_media)
@ -2831,7 +2797,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, ShouldCheckForImagePatches()); std::unique_ptr<CDImage> image = CDImage::Open(path, g_settings.cdrom_load_image_patches, &error);
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."),

View File

@ -161,7 +161,7 @@ void GameSummaryWidget::populateTracksInfo()
m_ui.tracks->clearContents(); m_ui.tracks->clearContents();
QtUtils::ResizeColumnsForTableView(m_ui.tracks, {70, 75, 95, 95, 215, 40}); QtUtils::ResizeColumnsForTableView(m_ui.tracks, {70, 75, 95, 95, 215, 40});
std::unique_ptr<CDImage> image = CDImage::Open(m_path.c_str(), nullptr); std::unique_ptr<CDImage> image = CDImage::Open(m_path.c_str(), false, nullptr);
if (!image) if (!image)
return; return;
@ -206,7 +206,7 @@ void GameSummaryWidget::onComputeHashClicked()
return; return;
} }
std::unique_ptr<CDImage> image = CDImage::Open(m_path.c_str(), nullptr); std::unique_ptr<CDImage> image = CDImage::Open(m_path.c_str(), false, nullptr);
if (!image) if (!image)
{ {
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Error"), tr("Failed to open CD image for hashing.")); QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Error"), tr("Failed to open CD image for hashing."));

View File

@ -1307,7 +1307,7 @@ void Achievements::GameChanged(const std::string& path, CDImage* image)
if (!path.empty() && (!image || (g_settings.achievements_use_first_disc_from_playlist && image->HasSubImages() && if (!path.empty() && (!image || (g_settings.achievements_use_first_disc_from_playlist && image->HasSubImages() &&
image->GetCurrentSubImage() != 0))) image->GetCurrentSubImage() != 0)))
{ {
temp_image = CDImage::Open(path.c_str(), nullptr); temp_image = CDImage::Open(path.c_str(), g_settings.cdrom_load_image_patches, nullptr);
image = temp_image.get(); image = temp_image.get();
if (!temp_image) if (!temp_image)
{ {
@ -1336,7 +1336,8 @@ void Achievements::GameChanged(const std::string& path, CDImage* image)
if (image && image->HasSubImages() && image->GetCurrentSubImage() != 0) if (image && image->HasSubImages() && image->GetCurrentSubImage() != 0)
{ {
std::unique_ptr<CDImage> image_copy(CDImage::Open(image->GetFileName().c_str(), nullptr)); std::unique_ptr<CDImage> image_copy(
CDImage::Open(image->GetFileName().c_str(), g_settings.cdrom_load_image_patches, nullptr));
if (!image_copy) if (!image_copy)
{ {
Log_ErrorPrintf("Failed to reopen image '%s'", image->GetFileName().c_str()); Log_ErrorPrintf("Failed to reopen image '%s'", image->GetFileName().c_str());

View File

@ -164,7 +164,7 @@ bool GameList::GetPsfListEntry(const std::string& path, Entry* entry)
bool GameList::GetDiscListEntry(const std::string& path, Entry* entry) bool GameList::GetDiscListEntry(const std::string& path, Entry* entry)
{ {
std::unique_ptr<CDImage> cdi = CDImage::Open(path.c_str(), nullptr); std::unique_ptr<CDImage> cdi = CDImage::Open(path.c_str(), false, nullptr);
if (!cdi) if (!cdi)
return false; return false;

View File

@ -1,5 +1,6 @@
#include "cd_image.h" #include "cd_image.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/error.h"
#include "common/file_system.h" #include "common/file_system.h"
#include "common/log.h" #include "common/log.h"
#include "common/path.h" #include "common/path.h"
@ -17,7 +18,7 @@ u32 CDImage::GetBytesPerSector(TrackMode mode)
return sizes[static_cast<u32>(mode)]; return sizes[static_cast<u32>(mode)];
} }
std::unique_ptr<CDImage> CDImage::Open(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::Open(const char* filename, bool allow_patches, Common::Error* error)
{ {
const char* extension; const char* extension;
@ -37,45 +38,69 @@ std::unique_ptr<CDImage> CDImage::Open(const char* filename, Common::Error* erro
return nullptr; return nullptr;
} }
std::unique_ptr<CDImage> image;
if (StringUtil::Strcasecmp(extension, ".cue") == 0) if (StringUtil::Strcasecmp(extension, ".cue") == 0)
{ {
return OpenCueSheetImage(filename, error); image = OpenCueSheetImage(filename, error);
} }
else if (StringUtil::Strcasecmp(extension, ".bin") == 0 || StringUtil::Strcasecmp(extension, ".img") == 0 || else if (StringUtil::Strcasecmp(extension, ".bin") == 0 || StringUtil::Strcasecmp(extension, ".img") == 0 ||
StringUtil::Strcasecmp(extension, ".iso") == 0) StringUtil::Strcasecmp(extension, ".iso") == 0)
{ {
return OpenBinImage(filename, error); image = OpenBinImage(filename, error);
} }
else if (StringUtil::Strcasecmp(extension, ".chd") == 0) else if (StringUtil::Strcasecmp(extension, ".chd") == 0)
{ {
return OpenCHDImage(filename, error); image = OpenCHDImage(filename, error);
} }
else if (StringUtil::Strcasecmp(extension, ".ecm") == 0) else if (StringUtil::Strcasecmp(extension, ".ecm") == 0)
{ {
return OpenEcmImage(filename, error); image = OpenEcmImage(filename, error);
} }
else if (StringUtil::Strcasecmp(extension, ".mds") == 0) else if (StringUtil::Strcasecmp(extension, ".mds") == 0)
{ {
return OpenMdsImage(filename, error); image = OpenMdsImage(filename, error);
} }
else if (StringUtil::Strcasecmp(extension, ".pbp") == 0) else if (StringUtil::Strcasecmp(extension, ".pbp") == 0)
{ {
return OpenPBPImage(filename, error); image = OpenPBPImage(filename, error);
} }
else if (StringUtil::Strcasecmp(extension, ".m3u") == 0) else if (StringUtil::Strcasecmp(extension, ".m3u") == 0)
{ {
return OpenM3uImage(filename, error); image = OpenM3uImage(filename, allow_patches, error);
} }
else if (IsDeviceName(filename))
if (IsDeviceName(filename)) {
return OpenDeviceImage(filename, error); image = OpenDeviceImage(filename, error);
}
#undef CASE_COMPARE else
{
Log_ErrorPrintf("Unknown extension '%s' from filename '%s'", extension, filename); Log_ErrorPrintf("Unknown extension '%s' from filename '%s'", extension, filename);
return nullptr; return nullptr;
} }
if (allow_patches)
{
#ifdef __ANDROID__
const std::string ppf_filename(
Path::BuildRelativePath(filename, Path::ReplaceExtension(filename_display_name, "ppf")));
#else
const std::string ppf_filename(
Path::BuildRelativePath(filename, Path::ReplaceExtension(Path::GetFileName(filename), "ppf")));
#endif
if (FileSystem::FileExists(ppf_filename.c_str()))
{
image = CDImage::OverlayPPFPatch(ppf_filename.c_str(), std::move(image));
if (!image)
{
if (error)
error->SetFormattedMessage("Failed to apply ppf patch from '%s'.", ppf_filename.c_str());
}
}
}
return image;
}
CDImage::LBA CDImage::GetTrackStartPosition(u8 track) const CDImage::LBA CDImage::GetTrackStartPosition(u8 track) const
{ {
Assert(track > 0 && track <= m_tracks.size()); Assert(track > 0 && track <= m_tracks.size());

View File

@ -217,14 +217,14 @@ public:
static bool IsDeviceName(const char* filename); static bool IsDeviceName(const char* filename);
// Opening disc image. // Opening disc image.
static std::unique_ptr<CDImage> Open(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> Open(const char* filename, bool allow_patches, Common::Error* error);
static std::unique_ptr<CDImage> OpenBinImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenBinImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage> OpenCueSheetImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenCueSheetImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage> OpenCHDImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenCHDImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage> OpenEcmImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenEcmImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage> OpenMdsImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenMdsImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage> OpenPBPImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenPBPImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage> OpenM3uImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenM3uImage(const char* filename, bool apply_patches, Common::Error* error);
static std::unique_ptr<CDImage> OpenDeviceImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenDeviceImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage> static std::unique_ptr<CDImage>
CreateMemoryImage(CDImage* image, ProgressCallback* progress = ProgressCallback::NullProgressCallback); CreateMemoryImage(CDImage* image, ProgressCallback* progress = ProgressCallback::NullProgressCallback);
@ -232,15 +232,42 @@ public:
ProgressCallback* progress = ProgressCallback::NullProgressCallback); ProgressCallback* progress = ProgressCallback::NullProgressCallback);
// Accessors. // Accessors.
const std::string& GetFileName() const { return m_filename; } const std::string& GetFileName() const
LBA GetPositionOnDisc() const { return m_position_on_disc; } {
Position GetMSFPositionOnDisc() const { return Position::FromLBA(m_position_on_disc); } return m_filename;
LBA GetPositionInTrack() const { return m_position_in_track; } }
Position GetMSFPositionInTrack() const { return Position::FromLBA(m_position_in_track); } LBA GetPositionOnDisc() const
LBA GetLBACount() const { return m_lba_count; } {
u32 GetIndexNumber() const { return m_current_index->index_number; } return m_position_on_disc;
u32 GetTrackNumber() const { return m_current_index->track_number; } }
u32 GetTrackCount() const { return static_cast<u32>(m_tracks.size()); } Position GetMSFPositionOnDisc() const
{
return Position::FromLBA(m_position_on_disc);
}
LBA GetPositionInTrack() const
{
return m_position_in_track;
}
Position GetMSFPositionInTrack() const
{
return Position::FromLBA(m_position_in_track);
}
LBA GetLBACount() const
{
return m_lba_count;
}
u32 GetIndexNumber() const
{
return m_current_index->index_number;
}
u32 GetTrackNumber() const
{
return m_current_index->track_number;
}
u32 GetTrackCount() const
{
return static_cast<u32>(m_tracks.size());
}
LBA GetTrackStartPosition(u8 track) const; LBA GetTrackStartPosition(u8 track) const;
Position GetTrackStartMSFPosition(u8 track) const; Position GetTrackStartMSFPosition(u8 track) const;
LBA GetTrackLength(u8 track) const; LBA GetTrackLength(u8 track) const;
@ -248,11 +275,26 @@ public:
TrackMode GetTrackMode(u8 track) const; TrackMode GetTrackMode(u8 track) const;
LBA GetTrackIndexPosition(u8 track, u8 index) const; LBA GetTrackIndexPosition(u8 track, u8 index) const;
LBA GetTrackIndexLength(u8 track, u8 index) const; LBA GetTrackIndexLength(u8 track, u8 index) const;
u32 GetFirstTrackNumber() const { return m_tracks.front().track_number; } u32 GetFirstTrackNumber() const
u32 GetLastTrackNumber() const { return m_tracks.back().track_number; } {
u32 GetIndexCount() const { return static_cast<u32>(m_indices.size()); } return m_tracks.front().track_number;
const std::vector<Track>& GetTracks() const { return m_tracks; } }
const std::vector<Index>& GetIndices() const { return m_indices; } u32 GetLastTrackNumber() const
{
return m_tracks.back().track_number;
}
u32 GetIndexCount() const
{
return static_cast<u32>(m_indices.size());
}
const std::vector<Track>& GetTracks() const
{
return m_tracks;
}
const std::vector<Index>& GetIndices() const
{
return m_indices;
}
const Track& GetTrack(u32 track) const; const Track& GetTrack(u32 track) const;
const Index& GetIndex(u32 i) const; const Index& GetIndex(u32 i) const;

View File

@ -17,7 +17,7 @@ public:
CDImageM3u(); CDImageM3u();
~CDImageM3u() override; ~CDImageM3u() override;
bool Open(const char* path, Common::Error* Error); bool Open(const char* path, bool apply_patches, Common::Error* Error);
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;
@ -42,13 +42,14 @@ private:
std::vector<Entry> m_entries; std::vector<Entry> m_entries;
std::unique_ptr<CDImage> m_current_image; std::unique_ptr<CDImage> m_current_image;
u32 m_current_image_index = UINT32_C(0xFFFFFFFF); u32 m_current_image_index = UINT32_C(0xFFFFFFFF);
bool m_apply_patches = false;
}; };
CDImageM3u::CDImageM3u() = default; CDImageM3u::CDImageM3u() = default;
CDImageM3u::~CDImageM3u() = default; CDImageM3u::~CDImageM3u() = default;
bool CDImageM3u::Open(const char* path, Common::Error* error) bool CDImageM3u::Open(const char* path, bool apply_patches, Common::Error* error)
{ {
std::FILE* fp = FileSystem::OpenCFile(path, "rb"); std::FILE* fp = FileSystem::OpenCFile(path, "rb");
if (!fp) if (!fp)
@ -65,6 +66,7 @@ bool CDImageM3u::Open(const char* path, Common::Error* error)
std::istringstream ifs(m3u_file.value()); std::istringstream ifs(m3u_file.value());
m_filename = path; m_filename = path;
m_apply_patches = apply_patches;
std::vector<std::string> entries; std::vector<std::string> entries;
std::string line; std::string line;
@ -131,7 +133,7 @@ bool CDImageM3u::SwitchSubImage(u32 index, Common::Error* error)
return true; return true;
const Entry& entry = m_entries[index]; const Entry& entry = m_entries[index];
std::unique_ptr<CDImage> new_image = CDImage::Open(entry.filename.c_str(), error); std::unique_ptr<CDImage> new_image = CDImage::Open(entry.filename.c_str(), m_apply_patches, error);
if (!new_image) if (!new_image)
{ {
Log_ErrorPrintf("Failed to load subimage %u (%s)", index, entry.filename.c_str()); Log_ErrorPrintf("Failed to load subimage %u (%s)", index, entry.filename.c_str());
@ -170,10 +172,10 @@ bool CDImageM3u::ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_
return m_current_image->ReadSubChannelQ(subq, index, lba_in_index); return m_current_image->ReadSubChannelQ(subq, index, lba_in_index);
} }
std::unique_ptr<CDImage> CDImage::OpenM3uImage(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenM3uImage(const char* filename, bool apply_patches, Common::Error* error)
{ {
std::unique_ptr<CDImageM3u> image = std::make_unique<CDImageM3u>(); std::unique_ptr<CDImageM3u> image = std::make_unique<CDImageM3u>();
if (!image->Open(filename, error)) if (!image->Open(filename, apply_patches, error))
return {}; return {};
return image; return image;