mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 23:55:40 +00:00
CDImage: Use Error class for complex errors
This commit is contained in:
parent
955afc3182
commit
11dcba1b68
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue