CDImage: Use Error class for complex errors

This commit is contained in:
Connor McLaughlin 2021-03-19 01:52:00 +10:00
parent 955afc3182
commit 11dcba1b68
14 changed files with 219 additions and 63 deletions

View file

@ -14,7 +14,7 @@ u32 CDImage::GetBytesPerSector(TrackMode mode)
return sizes[static_cast<u32>(mode)];
}
std::unique_ptr<CDImage> CDImage::Open(const char* filename)
std::unique_ptr<CDImage> CDImage::Open(const char* filename, Common::Error* error)
{
const char* extension = std::strrchr(filename, '.');
if (!extension)
@ -31,28 +31,28 @@ std::unique_ptr<CDImage> CDImage::Open(const char* filename)
if (CASE_COMPARE(extension, ".cue") == 0)
{
return OpenCueSheetImage(filename);
return OpenCueSheetImage(filename, error);
}
else if (CASE_COMPARE(extension, ".bin") == 0 || CASE_COMPARE(extension, ".img") == 0 ||
CASE_COMPARE(extension, ".iso") == 0)
{
return OpenBinImage(filename);
return OpenBinImage(filename, error);
}
else if (CASE_COMPARE(extension, ".chd") == 0)
{
return OpenCHDImage(filename);
return OpenCHDImage(filename, error);
}
else if (CASE_COMPARE(extension, ".ecm") == 0)
{
return OpenEcmImage(filename);
return OpenEcmImage(filename, error);
}
else if (CASE_COMPARE(extension, ".mds") == 0)
{
return OpenMdsImage(filename);
return OpenMdsImage(filename, error);
}
else if (CASE_COMPARE(extension, ".pbp") == 0)
{
return OpenPBPImage(filename);
return OpenPBPImage(filename, error);
}
#undef CASE_COMPARE

View file

@ -8,6 +8,10 @@
#include <tuple>
#include <vector>
namespace Common {
class Error;
}
class CDImage
{
public:
@ -191,13 +195,13 @@ public:
static u32 GetBytesPerSector(TrackMode mode);
// Opening disc image.
static std::unique_ptr<CDImage> Open(const char* filename);
static std::unique_ptr<CDImage> OpenBinImage(const char* filename);
static std::unique_ptr<CDImage> OpenCueSheetImage(const char* filename);
static std::unique_ptr<CDImage> OpenCHDImage(const char* filename);
static std::unique_ptr<CDImage> OpenEcmImage(const char* filename);
static std::unique_ptr<CDImage> OpenMdsImage(const char* filename);
static std::unique_ptr<CDImage> OpenPBPImage(const char* filename);
static std::unique_ptr<CDImage> Open(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> OpenCHDImage(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> OpenPBPImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage>
CreateMemoryImage(CDImage* image, ProgressCallback* progress = ProgressCallback::NullProgressCallback);

View file

@ -1,5 +1,6 @@
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "error.h"
#include "file_system.h"
#include "log.h"
#include <cerrno>
@ -11,7 +12,7 @@ public:
CDImageBin();
~CDImageBin() override;
bool Open(const char* filename);
bool Open(const char* filename, Common::Error* error);
bool ReadSubChannelQ(SubChannelQ* subq) override;
bool HasNonStandardSubchannel() const override;
@ -34,13 +35,15 @@ CDImageBin::~CDImageBin()
std::fclose(m_fp);
}
bool CDImageBin::Open(const char* filename)
bool CDImageBin::Open(const char* filename, Common::Error* error)
{
m_filename = filename;
m_fp = FileSystem::OpenCFile(filename, "rb");
if (!m_fp)
{
Log_ErrorPrintf("Failed to open binfile '%s': errno %d", filename, errno);
if (error)
error->SetErrno(errno);
return false;
}
@ -130,10 +133,10 @@ bool CDImageBin::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i
return true;
}
std::unique_ptr<CDImage> CDImage::OpenBinImage(const char* filename)
std::unique_ptr<CDImage> CDImage::OpenBinImage(const char* filename, Common::Error* error)
{
std::unique_ptr<CDImageBin> image = std::make_unique<CDImageBin>();
if (!image->Open(filename))
if (!image->Open(filename, error))
return {};
return image;

View file

@ -7,6 +7,7 @@
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "cpu_detect.h"
#include "error.h"
#include "file_system.h"
#include "libchdr/chd.h"
#include "log.h"
@ -46,7 +47,7 @@ public:
CDImageCHD();
~CDImageCHD() override;
bool Open(const char* filename);
bool Open(const char* filename, Common::Error* error);
bool ReadSubChannelQ(SubChannelQ* subq) override;
bool HasNonStandardSubchannel() const override;
@ -84,13 +85,16 @@ CDImageCHD::~CDImageCHD()
std::fclose(m_fp);
}
bool CDImageCHD::Open(const char* filename)
bool CDImageCHD::Open(const char* filename, Common::Error* error)
{
Assert(!m_fp);
m_fp = FileSystem::OpenCFile(filename, "rb");
if (!m_fp)
{
Log_ErrorPrintf("Failed to open CHD '%s': errno %d", filename, errno);
if (error)
error->SetErrno(errno);
return false;
}
@ -98,6 +102,9 @@ bool CDImageCHD::Open(const char* filename)
if (err != CHDERR_NONE)
{
Log_ErrorPrintf("Failed to open CHD '%s': %s", filename, chd_error_string(err));
if (error)
error->SetMessage(chd_error_string(err));
return false;
}
@ -106,6 +113,9 @@ bool CDImageCHD::Open(const char* filename)
if ((m_hunk_size % CHD_CD_SECTOR_DATA_SIZE) != 0)
{
Log_ErrorPrintf("Hunk size (%u) is not a multiple of %u", m_hunk_size, CHD_CD_SECTOR_DATA_SIZE);
if (error)
error->SetFormattedMessage("Hunk size (%u) is not a multiple of %u", m_hunk_size, CHD_CD_SECTOR_DATA_SIZE);
return false;
}
@ -136,6 +146,9 @@ bool CDImageCHD::Open(const char* filename)
&pregap_frames, pgtype_str, pgsub_str, &postgap_frames) != 8)
{
Log_ErrorPrintf("Invalid track v2 metadata: '%s'", metadata_str);
if (error)
error->SetFormattedMessage("Invalid track v2 metadata: '%s'", metadata_str);
return false;
}
}
@ -153,6 +166,9 @@ bool CDImageCHD::Open(const char* filename)
if (std::sscanf(metadata_str, CDROM_TRACK_METADATA_FORMAT, &track_num, type_str, subtype_str, &frames) != 4)
{
Log_ErrorPrintf("Invalid track metadata: '%s'", metadata_str);
if (error)
error->SetFormattedMessage("Invalid track v2 metadata: '%s'", metadata_str);
return false;
}
}
@ -161,6 +177,12 @@ bool CDImageCHD::Open(const char* filename)
{
Log_ErrorPrintf("Incorrect track number at index %d, expected %d got %d", num_tracks, (num_tracks + 1),
track_num);
if (error)
{
error->SetFormattedMessage("Incorrect track number at index %d, expected %d got %d", num_tracks,
(num_tracks + 1), track_num);
}
return false;
}
@ -168,6 +190,9 @@ bool CDImageCHD::Open(const char* filename)
if (!mode.has_value())
{
Log_ErrorPrintf("Invalid track mode: '%s'", type_str);
if (error)
error->SetFormattedMessage("Invalid track mode: '%s'", type_str);
return false;
}
@ -198,6 +223,9 @@ bool CDImageCHD::Open(const char* filename)
if (pregap_frames > frames)
{
Log_ErrorPrintf("Pregap length %u exceeds track length %u", pregap_frames, frames);
if (error)
error->SetFormattedMessage("Pregap length %u exceeds track length %u", pregap_frames, frames);
return false;
}
@ -242,6 +270,9 @@ bool CDImageCHD::Open(const char* filename)
if (m_tracks.empty())
{
Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error)
error->SetFormattedMessage("File '%s' contains no tracks", filename);
return false;
}
@ -343,10 +374,10 @@ bool CDImageCHD::ReadHunk(u32 hunk_index)
return true;
}
std::unique_ptr<CDImage> CDImage::OpenCHDImage(const char* filename)
std::unique_ptr<CDImage> CDImage::OpenCHDImage(const char* filename, Common::Error* error)
{
std::unique_ptr<CDImageCHD> image = std::make_unique<CDImageCHD>();
if (!image->Open(filename))
if (!image->Open(filename, error))
return {};
return image;

View file

@ -1,6 +1,7 @@
#include "assert.h"
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "error.h"
#include "file_system.h"
#include "log.h"
#include <algorithm>
@ -15,7 +16,7 @@ public:
CDImageCueSheet();
~CDImageCueSheet() override;
bool OpenAndParse(const char* filename);
bool OpenAndParse(const char* filename, Common::Error* error);
bool ReadSubChannelQ(SubChannelQ* subq) override;
bool HasNonStandardSubchannel() const override;
@ -45,12 +46,15 @@ CDImageCueSheet::~CDImageCueSheet()
cd_delete(m_cd);
}
bool CDImageCueSheet::OpenAndParse(const char* filename)
bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error)
{
std::optional<std::string> cuesheet_string = FileSystem::ReadFileToString(filename);
if (!cuesheet_string.has_value())
{
Log_ErrorPrintf("Failed to open cuesheet '%s': errno %d", filename, errno);
if (error)
error->SetErrno(errno);
return false;
}
@ -62,6 +66,9 @@ bool CDImageCueSheet::OpenAndParse(const char* filename)
if (!m_cd)
{
Log_ErrorPrintf("Failed to parse cuesheet '%s'", filename);
if (error)
error->SetMessage("Failed to parse cuesheet");
return false;
}
@ -80,6 +87,9 @@ bool CDImageCueSheet::OpenAndParse(const char* filename)
if (!track || !track_get_filename(track))
{
Log_ErrorPrintf("Track/filename missing for track %d", track_num);
if (error)
error->SetFormattedMessage("Track/filename missing for track %d", track_num);
return false;
}
@ -115,6 +125,12 @@ bool CDImageCueSheet::OpenAndParse(const char* filename)
{
Log_ErrorPrintf("Failed to open track filename '%s' (from '%s' and '%s'): errno %d",
track_full_filename.c_str(), track_filename.c_str(), filename, errno);
if (error)
{
error->SetFormattedMessage("Failed to open track filename '%s' (from '%s' and '%s'): errno %d",
track_full_filename.c_str(), track_filename.c_str(), filename, errno);
}
return false;
}
@ -142,8 +158,13 @@ bool CDImageCueSheet::OpenAndParse(const char* filename)
file_size /= track_sector_size;
if (track_start >= file_size)
{
Log_ErrorPrintf("Failed to open track %u in '%s': track start is out of range (%ld vs %ld)", track_num, filename,
track_start, file_size);
Log_ErrorPrintf("Failed to open track %u in '%s': track start is out of range (%ld vs %ld)", track_num,
filename, track_start, file_size);
if (error)
{
error->SetFormattedMessage("Failed to open track %u in '%s': track start is out of range (%ld vs %ld)",
track_num, filename, track_start, file_size);
}
return false;
}
@ -243,6 +264,8 @@ bool CDImageCueSheet::OpenAndParse(const char* filename)
if (m_tracks.empty())
{
Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error)
error->SetFormattedMessage("File '%s' contains no tracks", filename);
return false;
}
@ -291,10 +314,10 @@ bool CDImageCueSheet::ReadSectorFromIndex(void* buffer, const Index& index, LBA
return true;
}
std::unique_ptr<CDImage> CDImage::OpenCueSheetImage(const char* filename)
std::unique_ptr<CDImage> CDImage::OpenCueSheetImage(const char* filename, Common::Error* error)
{
std::unique_ptr<CDImageCueSheet> image = std::make_unique<CDImageCueSheet>();
if (!image->OpenAndParse(filename))
if (!image->OpenAndParse(filename, error))
return {};
return image;

View file

@ -1,6 +1,7 @@
#include "assert.h"
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "error.h"
#include "file_system.h"
#include "log.h"
#include <array>
@ -161,7 +162,7 @@ public:
CDImageEcm();
~CDImageEcm() override;
bool Open(const char* filename);
bool Open(const char* filename, Common::Error* error);
bool ReadSubChannelQ(SubChannelQ* subq) override;
bool HasNonStandardSubchannel() const override;
@ -221,13 +222,16 @@ CDImageEcm::~CDImageEcm()
std::fclose(m_fp);
}
bool CDImageEcm::Open(const char* filename)
bool CDImageEcm::Open(const char* filename, Common::Error* error)
{
m_filename = filename;
m_fp = FileSystem::OpenCFile(filename, "rb");
if (!m_fp)
{
Log_ErrorPrintf("Failed to open binfile '%s': errno %d", filename, errno);
if (error)
error->SetErrno(errno);
return false;
}
@ -236,6 +240,9 @@ bool CDImageEcm::Open(const char* filename)
header[3] != 0)
{
Log_ErrorPrintf("Failed to read/invalid header");
if (error)
error->SetMessage("Failed to read/invalid header");
return false;
}
@ -250,6 +257,9 @@ bool CDImageEcm::Open(const char* filename)
if (bits == EOF)
{
Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size());
if (error)
error->SetFormattedMessage("Unexpected EOF after %zu chunks", m_data_map.size());
return false;
}
@ -263,6 +273,9 @@ bool CDImageEcm::Open(const char* filename)
if (bits == EOF)
{
Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size());
if (error)
error->SetFormattedMessage("Unexpected EOF after %zu chunks", m_data_map.size());
return false;
}
@ -280,6 +293,9 @@ bool CDImageEcm::Open(const char* filename)
if (count >= 0x80000000u)
{
Log_ErrorPrintf("Corrupted header after %zu chunks", m_data_map.size());
if (error)
error->SetFormattedMessage("Corrupted header after %zu chunks", m_data_map.size());
return false;
}
@ -309,6 +325,9 @@ bool CDImageEcm::Open(const char* filename)
if (std::fseek(m_fp, file_offset, SEEK_SET) != 0)
{
Log_ErrorPrintf("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size());
if (error)
error->SetFormattedMessage("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size());
return false;
}
}
@ -316,6 +335,9 @@ bool CDImageEcm::Open(const char* filename)
if (m_data_map.empty())
{
Log_ErrorPrintf("No data in image '%s'", filename);
if (error)
error->SetFormattedMessage("No data in image '%s'", filename);
return false;
}
@ -501,10 +523,10 @@ bool CDImageEcm::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i
return true;
}
std::unique_ptr<CDImage> CDImage::OpenEcmImage(const char* filename)
std::unique_ptr<CDImage> CDImage::OpenEcmImage(const char* filename, Common::Error* error)
{
std::unique_ptr<CDImageEcm> image = std::make_unique<CDImageEcm>();
if (!image->Open(filename))
if (!image->Open(filename, error))
return {};
return image;

View file

@ -1,6 +1,7 @@
#include "assert.h"
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "error.h"
#include "file_system.h"
#include "log.h"
#include <algorithm>
@ -34,7 +35,7 @@ public:
CDImageMds();
~CDImageMds() override;
bool OpenAndParse(const char* filename);
bool OpenAndParse(const char* filename, Common::Error* error);
bool ReadSubChannelQ(SubChannelQ* subq) override;
bool HasNonStandardSubchannel() const override;
@ -56,12 +57,15 @@ CDImageMds::~CDImageMds()
std::fclose(m_mdf_file);
}
bool CDImageMds::OpenAndParse(const char* filename)
bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
{
std::FILE* mds_fp = FileSystem::OpenCFile(filename, "rb");
if (!mds_fp)
{
Log_ErrorPrintf("Failed to open mds '%s': errno %d", filename, errno);
if (error)
error->SetErrno(errno);
return false;
}
@ -70,6 +74,9 @@ bool CDImageMds::OpenAndParse(const char* filename)
if (!mds_data_opt.has_value() || mds_data_opt->size() < 0x54)
{
Log_ErrorPrintf("Failed to read mds file '%s'", filename);
if (error)
error->SetFormattedMessage("Failed to read mds file '%s'", filename);
return false;
}
@ -78,6 +85,9 @@ bool CDImageMds::OpenAndParse(const char* filename)
if (!m_mdf_file)
{
Log_ErrorPrintf("Failed to open mdf file '%s': errno %d", mdf_filename.c_str(), errno);
if (error)
error->SetFormattedMessage("Failed to open mdf file '%s': errno %d", mdf_filename.c_str(), errno);
return false;
}
@ -86,6 +96,9 @@ bool CDImageMds::OpenAndParse(const char* filename)
if (std::memcmp(&mds[0], expected_signature, sizeof(expected_signature) - 1) != 0)
{
Log_ErrorPrintf("Incorrect signature in '%s'", filename);
if (error)
error->SetFormattedMessage("Incorrect signature in '%s'", filename);
return false;
}
@ -94,6 +107,9 @@ bool CDImageMds::OpenAndParse(const char* filename)
if ((session_offset + 24) > mds.size())
{
Log_ErrorPrintf("Invalid session offset in '%s'", filename);
if (error)
error->SetFormattedMessage("Invalid session offset in '%s'", filename);
return false;
}
@ -104,6 +120,9 @@ bool CDImageMds::OpenAndParse(const char* filename)
if (track_count > 99 || track_offset >= mds.size())
{
Log_ErrorPrintf("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename);
if (error)
error->SetFormattedMessage("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename);
return false;
}
@ -122,6 +141,9 @@ bool CDImageMds::OpenAndParse(const char* filename)
if ((track_offset + sizeof(TrackEntry)) > mds.size())
{
Log_ErrorPrintf("End of file in '%s' at track %u", filename, track_number);
if (error)
error->SetFormattedMessage("End of file in '%s' at track %u", filename, track_number);
return false;
}
@ -130,9 +152,12 @@ bool CDImageMds::OpenAndParse(const char* filename)
if (PackedBCDToBinary(track.track_number) != track_number)
{
Log_ErrorPrintf("Unexpected track number 0x%02X in track %u", track.track_number, track_number);
if (error)
error->SetFormattedMessage("Unexpected track number 0x%02X in track %u", track.track_number, track_number);
return false;
}
const bool contains_subchannel = (track.has_subchannel_data != 0);
const u32 track_sector_size = (contains_subchannel ? 2448 : RAW_SECTOR_SIZE);
const TrackMode mode = (track.track_type == 0xA9) ? TrackMode::Audio : TrackMode::Mode2Raw;
@ -140,6 +165,9 @@ bool CDImageMds::OpenAndParse(const char* filename)
if ((track.extra_offset + sizeof(u32) + sizeof(u32)) > mds.size())
{
Log_ErrorPrintf("Invalid extra offset %u in track %u", track.extra_offset, track_number);
if (error)
error->SetFormattedMessage("Invalid extra offset %u in track %u", track.extra_offset, track_number);
return false;
}
@ -162,6 +190,9 @@ bool CDImageMds::OpenAndParse(const char* filename)
if (track_pregap > track_start_lba)
{
Log_ErrorPrintf("Track pregap %u is too large for start lba %u", track_pregap, track_start_lba);
if (error)
error->SetFormattedMessage("Track pregap %u is too large for start lba %u", track_pregap, track_start_lba);
return false;
}
@ -210,6 +241,9 @@ bool CDImageMds::OpenAndParse(const char* filename)
if (m_tracks.empty())
{
Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error)
error->SetFormattedMessage("File '%s' contains no tracks", filename);
return false;
}
@ -257,10 +291,10 @@ bool CDImageMds::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i
return true;
}
std::unique_ptr<CDImage> CDImage::OpenMdsImage(const char* filename)
std::unique_ptr<CDImage> CDImage::OpenMdsImage(const char* filename, Common::Error* error)
{
std::unique_ptr<CDImageMds> image = std::make_unique<CDImageMds>();
if (!image->OpenAndParse(filename))
if (!image->OpenAndParse(filename, error))
return {};
return image;

View file

@ -1,5 +1,6 @@
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "error.h"
#include "file_system.h"
#include "log.h"
#include "pbp_types.h"
@ -18,7 +19,7 @@ public:
CDImagePBP() = default;
~CDImagePBP() override;
bool Open(const char* filename);
bool Open(const char* filename, Common::Error* error);
bool ReadSubChannelQ(SubChannelQ* subq) override;
bool HasNonStandardSubchannel() const override;
@ -45,7 +46,7 @@ private:
bool LoadSFOIndexTable();
bool LoadSFOTable();
bool IsValidEboot();
bool IsValidEboot(Common::Error* error);
bool InitDecompressionStream();
bool DecompressBlock(BlockInfo block_info);
@ -257,7 +258,7 @@ bool CDImagePBP::LoadSFOTable()
return true;
}
bool CDImagePBP::IsValidEboot()
bool CDImagePBP::IsValidEboot(Common::Error* error)
{
// Check some fields to make sure this is a valid PS1 EBOOT.PBP
@ -268,12 +269,16 @@ bool CDImagePBP::IsValidEboot()
if (!std::holds_alternative<u32>(data_value) || std::get<u32>(data_value) != 1)
{
Log_ErrorPrint("Invalid BOOTABLE value");
if (error)
error->SetMessage("Invalid BOOTABLE value");
return false;
}
}
else
{
Log_ErrorPrint("No BOOTABLE value found");
if (error)
error->SetMessage("No BOOTABLE value found");
return false;
}
@ -284,19 +289,23 @@ bool CDImagePBP::IsValidEboot()
if (!std::holds_alternative<std::string>(data_value) || std::get<std::string>(data_value) != "ME")
{
Log_ErrorPrint("Invalid CATEGORY value");
if (error)
error->SetMessage("Invalid CATEGORY value");
return false;
}
}
else
{
Log_ErrorPrint("No CATEGORY value found");
if (error)
error->SetMessage("No CATEGORY value found");
return false;
}
return true;
}
bool CDImagePBP::Open(const char* filename)
bool CDImagePBP::Open(const char* filename, Common::Error* error)
{
if (!EndianHelper::HostIsLittleEndian())
{
@ -306,7 +315,12 @@ bool CDImagePBP::Open(const char* filename)
m_file = FileSystem::OpenCFile(filename, "rb");
if (!m_file)
{
if (error)
error->SetErrno(errno);
return false;
}
m_filename = filename;
@ -314,6 +328,8 @@ bool CDImagePBP::Open(const char* filename)
if (!LoadPBPHeader())
{
Log_ErrorPrint("Failed to load PBP header");
if (error)
error->SetMessage("Failed to load PBP header");
return false;
}
@ -321,6 +337,8 @@ bool CDImagePBP::Open(const char* filename)
if (!LoadSFOHeader())
{
Log_ErrorPrint("Failed to load SFO header");
if (error)
error->SetMessage("Failed to load SFO header");
return false;
}
@ -328,6 +346,8 @@ bool CDImagePBP::Open(const char* filename)
if (!LoadSFOIndexTable())
{
Log_ErrorPrint("Failed to load SFO index table");
if (error)
error->SetMessage("Failed to load SFO index table");
return false;
}
@ -335,11 +355,13 @@ bool CDImagePBP::Open(const char* filename)
if (!LoadSFOTable())
{
Log_ErrorPrint("Failed to load SFO table");
if (error)
error->SetMessage("Failed to load SFO table");
return false;
}
// Since PBP files can store things that aren't PS1 CD images, make sure we're loading the right kind
if (!IsValidEboot())
if (!IsValidEboot(error))
{
Log_ErrorPrint("Couldn't validate EBOOT");
return false;
@ -372,6 +394,9 @@ bool CDImagePBP::Open(const char* filename)
if (disc_table[0] == 0x44475000) // "\0PGD"
{
Log_ErrorPrint("Encrypted PBP images are not supported");
if (error)
error->SetMessage("Encrypted PBP images are not supported");
return false;
}
@ -421,6 +446,9 @@ bool CDImagePBP::Open(const char* filename)
if (pgd_magic == 0x44475000) // "\0PGD"
{
Log_ErrorPrint("Encrypted PBP images are not supported");
if (error)
error->SetMessage("Encrypted PBP images are not supported");
return false;
}
@ -739,10 +767,10 @@ void CDImagePBP::PrintSFOTable(const SFOTable& sfo_table)
}
#endif
std::unique_ptr<CDImage> CDImage::OpenPBPImage(const char* filename)
std::unique_ptr<CDImage> CDImage::OpenPBPImage(const char* filename, Common::Error* error)
{
std::unique_ptr<CDImagePBP> image = std::make_unique<CDImagePBP>();
if (!image->Open(filename))
if (!image->Open(filename, error))
return {};
return image;

View file

@ -68,6 +68,7 @@
<ClInclude Include="d3d11\texture.h" />
<ClInclude Include="dimensional_array.h" />
<ClInclude Include="easing.h" />
<ClInclude Include="error.h" />
<ClInclude Include="event.h" />
<ClInclude Include="fifo_queue.h" />
<ClInclude Include="file_system.h" />
@ -142,6 +143,7 @@
<ClCompile Include="d3d11\staging_texture.cpp" />
<ClCompile Include="d3d11\stream_buffer.cpp" />
<ClCompile Include="d3d11\texture.cpp" />
<ClCompile Include="error.cpp" />
<ClCompile Include="event.cpp" />
<ClCompile Include="file_system.cpp" />
<ClCompile Include="gl\context.cpp" />

View file

@ -111,6 +111,7 @@
<ClInclude Include="lru_cache.h" />
<ClInclude Include="easing.h" />
<ClInclude Include="pbp_types.h" />
<ClInclude Include="error.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="jit_code_buffer.cpp" />
@ -214,6 +215,7 @@
<ClCompile Include="cd_image_ecm.cpp" />
<ClCompile Include="cd_image_mds.cpp" />
<ClCompile Include="cd_image_pbp.cpp" />
<ClCompile Include="error.cpp" />
</ItemGroup>
<ItemGroup>
<Natvis Include="bitfield.natvis" />

View file

@ -4,6 +4,7 @@
#include "cdrom.h"
#include "cheats.h"
#include "common/audio_stream.h"
#include "common/error.h"
#include "common/file_system.h"
#include "common/iso_reader.h"
#include "common/log.h"
@ -66,7 +67,7 @@ static bool LoadEXE(const char* filename);
static bool SetExpansionROM(const char* filename);
/// Opens CD image, preloading if needed.
static std::unique_ptr<CDImage> OpenCDImage(const char* path, bool force_preload);
static std::unique_ptr<CDImage> OpenCDImage(const char* path, Common::Error* error, bool force_preload);
static bool DoLoadState(ByteStream* stream, bool force_software_renderer, bool update_display);
static bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display);
@ -388,7 +389,7 @@ std::string_view GetTitleForPath(const char* path)
std::string GetGameCodeForPath(const char* image_path, bool fallback_to_hash)
{
std::unique_ptr<CDImage> cdi = CDImage::Open(image_path);
std::unique_ptr<CDImage> cdi = CDImage::Open(image_path, nullptr);
if (!cdi)
return {};
@ -656,7 +657,7 @@ std::optional<DiscRegion> GetRegionForPath(const char* image_path)
else if (IsPsfFileName(image_path))
return GetRegionForPsf(image_path);
std::unique_ptr<CDImage> cdi = CDImage::Open(image_path);
std::unique_ptr<CDImage> cdi = CDImage::Open(image_path, nullptr);
if (!cdi)
return {};
@ -704,9 +705,9 @@ bool RecreateGPU(GPURenderer renderer, bool update_display /* = true*/)
return true;
}
std::unique_ptr<CDImage> OpenCDImage(const char* path, bool force_preload)
std::unique_ptr<CDImage> OpenCDImage(const char* path, Common::Error* error, bool force_preload)
{
std::unique_ptr<CDImage> media = CDImage::Open(path);
std::unique_ptr<CDImage> media = CDImage::Open(path, error);
if (!media)
return {};
@ -796,12 +797,14 @@ bool Boot(const SystemBootParameters& params)
playlist_index = 0;
}
Common::Error error;
const std::string& media_path = s_media_playlist[playlist_index];
Log_InfoPrintf("Loading CD image '%s' from playlist index %u...", media_path.c_str(), playlist_index);
media = OpenCDImage(media_path.c_str(), params.load_image_to_ram);
media = OpenCDImage(media_path.c_str(), &error, params.load_image_to_ram);
if (!media)
{
g_host_interface->ReportFormattedError("Failed to load CD image '%s'", params.filename.c_str());
g_host_interface->ReportFormattedError("Failed to load CD image '%s': %s", params.filename.c_str(),
error.GetCodeAndMessage().GetCharArray());
Shutdown();
return false;
}
@ -1215,22 +1218,24 @@ bool DoLoadState(ByteStream* state, bool force_software_renderer, bool update_di
}
else
{
media = OpenCDImage(media_filename.c_str(), false);
Common::Error error;
media = OpenCDImage(media_filename.c_str(), &error, false);
if (!media)
{
if (old_media)
{
g_host_interface->AddFormattedOSDMessage(
30.0f,
g_host_interface->TranslateString("OSDMessage", "Failed to open CD image from save state: '%s'. Using "
g_host_interface->TranslateString("OSDMessage", "Failed to open CD image from save state '%s': %s. Using "
"existing image '%s', this may result in instability."),
media_filename.c_str(), old_media->GetFileName().c_str());
media_filename.c_str(), error.GetCodeAndMessage().GetCharArray(), old_media->GetFileName().c_str());
media = std::move(old_media);
}
else
{
g_host_interface->ReportFormattedError(
g_host_interface->TranslateString("System", "Failed to open CD image from save state: '%s'."),
g_host_interface->TranslateString("System", "Failed to open CD image from save state '%s': %s.",
error.GetCodeAndMessage().GetCharArray()),
media_filename.c_str());
return false;
}
@ -1965,11 +1970,13 @@ std::string GetMediaFileName()
bool InsertMedia(const char* path)
{
std::unique_ptr<CDImage> image = OpenCDImage(path, false);
Common::Error error;
std::unique_ptr<CDImage> image = OpenCDImage(path, &error, false);
if (!image)
{
g_host_interface->AddFormattedOSDMessage(
10.0f, g_host_interface->TranslateString("OSDMessage", "Failed to open disc image '%s'."), path);
10.0f, g_host_interface->TranslateString("OSDMessage", "Failed to open disc image '%s': %s."), path,
error.GetCodeAndMessage().GetCharArray());
return false;
}

View file

@ -224,7 +224,7 @@ void GamePropertiesDialog::populateTracksInfo(const std::string& image_path)
m_ui.tracks->clearContents();
m_path = image_path;
std::unique_ptr<CDImage> image = CDImage::Open(image_path.c_str());
std::unique_ptr<CDImage> image = CDImage::Open(image_path.c_str(), nullptr);
if (!image)
return;
@ -860,7 +860,7 @@ void GamePropertiesDialog::computeTrackHashes()
if (m_path.empty())
return;
std::unique_ptr<CDImage> image = CDImage::Open(m_path.c_str());
std::unique_ptr<CDImage> image = CDImage::Open(m_path.c_str(), nullptr);
if (!image)
return;

View file

@ -816,7 +816,7 @@ void GameChanged()
if (path.empty() || s_game_path == path)
return;
std::unique_ptr<CDImage> cdi = CDImage::Open(path.c_str());
std::unique_ptr<CDImage> cdi = CDImage::Open(path.c_str(), nullptr);
if (!cdi)
{
Log_ErrorPrintf("Failed to open temporary CD image '%s'", path.c_str());
@ -855,7 +855,7 @@ void GameChanged(const std::string& path, CDImage* image)
if (playlist_index > 0 && playlist_index < playlist_count)
{
const std::string& first_disc_path(System::GetMediaPlaylistPath(0));
std::unique_ptr<CDImage> first_disc_image(CDImage::Open(first_disc_path.c_str()));
std::unique_ptr<CDImage> first_disc_image(CDImage::Open(first_disc_path.c_str(), nullptr));
if (first_disc_image)
{
Log_InfoPrintf("Using first disc '%s' from playlist (currently '%s')", first_disc_path.c_str(), path.c_str());

View file

@ -168,7 +168,7 @@ bool GameList::GetM3UListEntry(const char* path, GameListEntry* entry)
for (size_t i = 0; i < entries.size(); i++)
{
std::unique_ptr<CDImage> entry_image = CDImage::Open(entries[i].c_str());
std::unique_ptr<CDImage> entry_image = CDImage::Open(entries[i].c_str(), nullptr);
if (!entry_image)
{
Log_ErrorPrintf("Failed to open entry %zu ('%s') in playlist %s", i, entries[i].c_str(), path);
@ -203,7 +203,7 @@ bool GameList::GetGameListEntry(const std::string& path, GameListEntry* entry)
if (System::IsM3UFileName(path.c_str()))
return GetM3UListEntry(path.c_str(), entry);
std::unique_ptr<CDImage> cdi = CDImage::Open(path.c_str());
std::unique_ptr<CDImage> cdi = CDImage::Open(path.c_str(), nullptr);
if (!cdi)
return false;