Common: Error/FileSystem backports

This commit is contained in:
Stenzek 2023-08-19 23:40:36 +10:00
parent 7890051165
commit 39f64a03ee
18 changed files with 311 additions and 555 deletions

View File

@ -1,182 +1,140 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "error.h" #include "error.h"
#include "string_util.h"
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <type_traits> #include <type_traits>
// Platform-specific includes #include "fmt/format.h"
#if defined(_WIN32) #if defined(_WIN32)
#include "windows_headers.h" #include "windows_headers.h"
static_assert(std::is_same<DWORD, unsigned long>::value, "DWORD is unsigned long");
static_assert(std::is_same<HRESULT, long>::value, "HRESULT is long");
#endif #endif
namespace Common { Error::Error() = default;
Error::Error() : m_type(Type::None) Error::Error(const Error& c) = default;
{
m_error.none = 0;
}
Error::Error(const Error& c) Error::Error(Error&& e) = default;
{
m_type = c.m_type;
std::memcpy(&m_error, &c.m_error, sizeof(m_error));
m_code_string.AppendString(c.m_code_string);
m_message.AppendString(c.m_message);
}
Error::~Error() = default; Error::~Error() = default;
void Error::Clear() void Error::Clear()
{ {
m_type = Type::None; m_description = {};
m_error.none = 0;
m_code_string.Clear();
m_message.Clear();
} }
void Error::SetErrno(int err) void Error::SetErrno(int err)
{ {
m_type = Type::Errno; m_type = Type::Errno;
m_error.errno_f = err;
m_code_string.Format("%i", err);
#ifdef _MSC_VER #ifdef _MSC_VER
strerror_s(m_message.GetWriteableCharArray(), m_message.GetBufferSize(), err); char buf[128];
m_message.UpdateSize(); if (strerror_s(buf, sizeof(buf), err) != 0)
#else m_description = fmt::format("errno {}: {}", err, buf);
const char* message = std::strerror(err);
if (message)
m_message = message;
else else
m_message = StaticString("<Could not get error message>"); m_description = fmt::format("errno {}: <Could not get error message>", err);
#endif
}
void Error::SetSocket(int err)
{
// Socket errors are win32 errors on windows
#ifdef _WIN32
SetWin32(err);
#else #else
SetErrno(err); const char* buf = std::strerror(err);
if (buf)
m_description = fmt::format("errno {}: {}", err, buf);
else
m_description = fmt::format("errno {}: <Could not get error message>", err);
#endif #endif
} }
void Error::SetMessage(const char* msg) void Error::SetErrno(Error* errptr, int err)
{ {
m_type = Type::User; if (errptr)
m_error.user = 0; errptr->SetErrno(err);
m_code_string.Clear();
m_message = msg;
} }
void Error::SetUser(int err, const char* msg) void Error::SetString(std::string description)
{ {
m_type = Type::User; m_type = Type::User;
m_error.user = err; m_description = std::move(description);
m_code_string.Format("%d", err);
m_message = msg;
} }
void Error::SetUser(const char* code, const char* message) void Error::SetString(Error* errptr, std::string description)
{ {
m_type = Type::User; if (errptr)
m_error.user = 0; errptr->SetString(std::move(description));
m_code_string = code;
m_message = message;
}
void Error::SetUserFormatted(int err, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
m_type = Type::User;
m_error.user = err;
m_code_string.Format("%d", err);
m_message.FormatVA(format, ap);
va_end(ap);
}
void Error::SetUserFormatted(const char* code, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
m_type = Type::User;
m_error.user = 0;
m_code_string = code;
m_message.FormatVA(format, ap);
va_end(ap);
}
void Error::SetFormattedMessage(const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
m_type = Type::User;
m_error.user = 0;
m_code_string.Clear();
m_message.FormatVA(format, ap);
va_end(ap);
} }
#ifdef _WIN32 #ifdef _WIN32
void Error::SetWin32(unsigned long err) void Error::SetWin32(unsigned long err)
{ {
m_type = Type::Win32; m_type = Type::Win32;
m_error.win32 = err;
m_code_string.Format("%u", static_cast<u32>(err));
m_message.Clear();
const DWORD r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, m_error.win32, 0, m_message.GetWriteableCharArray(), WCHAR buf[128];
m_message.GetWritableBufferSize(), NULL); const DWORD r = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_USER_DEFAULT, buf,
static_cast<DWORD>(std::size(buf)), nullptr);
if (r > 0) if (r > 0)
{ {
m_message.Resize(r); m_description =
m_message.RStrip(); fmt::format("Win32 Error {}: {}", err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
} }
else else
{ {
m_message = "<Could not resolve system error ID>"; m_description = fmt::format("Win32 Error {}: <Could not resolve system error ID>", err);
} }
} }
void Error::SetWin32(Error* errptr, unsigned long err)
{
if (errptr)
errptr->SetWin32(err);
}
void Error::SetHResult(long err) void Error::SetHResult(long err)
{ {
m_type = Type::HResult; m_type = Type::HResult;
m_error.win32 = err;
m_code_string.Format("%08X", static_cast<u32>(err));
m_message.Clear();
const DWORD r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, m_error.win32, 0, m_message.GetWriteableCharArray(), WCHAR buf[128];
m_message.GetWritableBufferSize(), NULL); const DWORD r = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_USER_DEFAULT, buf,
static_cast<DWORD>(std::size(buf)), nullptr);
if (r > 0) if (r > 0)
{ {
m_message.Resize(r); m_description =
m_message.RStrip(); fmt::format("HRESULT {:08X}: {}", err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
} }
else else
{ {
m_message = "<Could not resolve system error ID>"; m_description = fmt::format("HRESULT {:08X}: <Could not resolve system error ID>", err);
} }
} }
void Error::SetHResult(Error* errptr, long err)
{
if (errptr)
errptr->SetHResult(err);
}
#endif #endif
// constructors void Error::SetSocket(int err)
{
// Socket errors are win32 errors on windows
#ifdef _WIN32
SetWin32(err);
#else
SetErrno(err);
#endif
m_type = Type::Socket;
}
void Error::SetSocket(Error* errptr, int err)
{
if (errptr)
errptr->SetSocket(err);
}
Error Error::CreateNone() Error Error::CreateNone()
{ {
Error ret; return Error();
ret.Clear();
return ret;
} }
Error Error::CreateErrno(int err) Error Error::CreateErrno(int err)
@ -193,70 +151,10 @@ Error Error::CreateSocket(int err)
return ret; return ret;
} }
Error Error::CreateMessage(const char* msg) Error Error::CreateString(std::string description)
{ {
Error ret; Error ret;
ret.SetMessage(msg); ret.SetString(std::move(description));
return ret;
}
Error Error::CreateUser(int err, const char* msg)
{
Error ret;
ret.SetUser(err, msg);
return ret;
}
Error Error::CreateUser(const char* code, const char* message)
{
Error ret;
ret.SetUser(code, message);
return ret;
}
Error Error::CreateMessageFormatted(const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
Error ret;
ret.m_type = Type::User;
ret.m_message.FormatVA(format, ap);
va_end(ap);
return ret;
}
Error Error::CreateUserFormatted(int err, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
Error ret;
ret.m_type = Type::User;
ret.m_error.user = err;
ret.m_code_string.Format("%d", err);
ret.m_message.FormatVA(format, ap);
va_end(ap);
return ret;
}
Error Error::CreateUserFormatted(const char* code, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
Error ret;
ret.m_type = Type::User;
ret.m_error.user = 0;
ret.m_code_string = code;
ret.m_message.FormatVA(format, ap);
va_end(ap);
return ret; return ret;
} }
@ -277,86 +175,16 @@ Error Error::CreateHResult(long err)
#endif #endif
Error& Error::operator=(const Error& e) Error& Error::operator=(const Error& e) = default;
{
m_type = e.m_type; Error& Error::operator=(Error&& e) = default;
std::memcpy(&m_error, &e.m_error, sizeof(m_error));
m_code_string.Clear();
m_code_string.AppendString(e.m_code_string);
m_message.Clear();
m_message.AppendString(e.m_message);
return *this;
}
bool Error::operator==(const Error& e) const bool Error::operator==(const Error& e) const
{ {
switch (m_type) return (m_type == e.m_type && m_description == e.m_description);
{
case Type::None:
return true;
case Type::Errno:
return m_error.errno_f == e.m_error.errno_f;
case Type::Socket:
return m_error.socketerr == e.m_error.socketerr;
case Type::User:
return m_error.user == e.m_error.user;
#ifdef _WIN32
case Type::Win32:
return m_error.win32 == e.m_error.win32;
case Type::HResult:
return m_error.hresult == e.m_error.hresult;
#endif
}
return false;
} }
bool Error::operator!=(const Error& e) const bool Error::operator!=(const Error& e) const
{ {
switch (m_type) return (m_type != e.m_type || m_description != e.m_description);
{ }
case Type::None:
return false;
case Type::Errno:
return m_error.errno_f != e.m_error.errno_f;
case Type::Socket:
return m_error.socketerr != e.m_error.socketerr;
case Type::User:
return m_error.user != e.m_error.user;
#ifdef _WIN32
case Type::Win32:
return m_error.win32 != e.m_error.win32;
case Type::HResult:
return m_error.hresult != e.m_error.hresult;
#endif
}
return true;
}
SmallString Error::GetCodeAndMessage() const
{
SmallString ret;
GetCodeAndMessage(ret);
return ret;
}
void Error::GetCodeAndMessage(String& dest) const
{
if (m_code_string.IsEmpty())
dest.Assign(m_message);
else
dest.Format("[%s]: %s", m_code_string.GetCharArray(), m_message.GetCharArray());
}
} // namespace Common

View File

@ -1,100 +1,75 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once #pragma once
#include "string.h"
#include "types.h" #include "types.h"
namespace Common { #include <string>
// this class provides enough storage room for all of these types
class Error class Error
{ {
public: public:
Error(); Error();
Error(const Error& e); Error(const Error& e);
Error(Error&& e);
~Error(); ~Error();
enum class Type enum class Type
{ {
None = 0, // Set by default constructor, returns 'No Error'. None = 0,
Errno = 1, // Error that is set by system functions, such as open(). Errno = 1,
Socket = 2, // Error that is set by socket functions, such as socket(). On Unix this is the same as errno. Socket = 2,
User = 3, // When translated, will return 'User Error %u' if no message is specified. User = 3,
Win32 = 4, // Error that is returned by some Win32 functions, such as RegOpenKeyEx. Also used by other APIs through Win32 = 4,
// GetLastError(). HResult = 5,
HResult = 5, // Error that is returned by Win32 COM methods, e.g. S_OK.
}; };
ALWAYS_INLINE Type GetType() const { return m_type; } ALWAYS_INLINE Type GetType() const { return m_type; }
ALWAYS_INLINE int GetErrnoCode() const { return m_error.errno_f; } ALWAYS_INLINE const std::string& GetDescription() const { return m_description; }
ALWAYS_INLINE int GetSocketCode() const { return m_error.socketerr; }
ALWAYS_INLINE int GetUserCode() const { return m_error.user; }
#ifdef _WIN32
ALWAYS_INLINE unsigned long GetWin32Code() const { return m_error.win32; }
ALWAYS_INLINE long GetHResultCode() const { return m_error.hresult; }
#endif
// get code, e.g. "0x00000002"
ALWAYS_INLINE const String& GetCodeString() const { return m_code_string; }
// get description, e.g. "File not Found"
ALWAYS_INLINE const String& GetMessage() const { return m_message; }
// setter functions
void Clear(); void Clear();
/// Error that is set by system functions, such as open().
void SetErrno(int err); void SetErrno(int err);
/// Error that is set by socket functions, such as socket(). On Unix this is the same as errno.
void SetSocket(int err); void SetSocket(int err);
void SetMessage(const char* msg);
void SetFormattedMessage(const char* format, ...) printflike(2, 3); /// Set both description and message.
void SetUser(int err, const char* msg); void SetString(std::string description);
void SetUser(const char* code, const char* message);
void SetUserFormatted(int err, const char* format, ...) printflike(3, 4);
void SetUserFormatted(const char* code, const char* format, ...) printflike(3, 4);
#ifdef _WIN32 #ifdef _WIN32
/// Error that is returned by some Win32 functions, such as RegOpenKeyEx. Also used by other APIs through
/// GetLastError().
void SetWin32(unsigned long err); void SetWin32(unsigned long err);
/// Error that is returned by Win32 COM methods, e.g. S_OK.
void SetHResult(long err); void SetHResult(long err);
#endif #endif
// constructors
static Error CreateNone(); static Error CreateNone();
static Error CreateErrno(int err); static Error CreateErrno(int err);
static Error CreateSocket(int err); static Error CreateSocket(int err);
static Error CreateMessage(const char* msg); static Error CreateString(std::string description);
static Error CreateMessageFormatted(const char* format, ...) printflike(1, 2);
static Error CreateUser(int err, const char* msg);
static Error CreateUser(const char* code, const char* message);
static Error CreateUserFormatted(int err, const char* format, ...) printflike(2, 3);
static Error CreateUserFormatted(const char* code, const char* format, ...) printflike(2, 3);
#ifdef _WIN32 #ifdef _WIN32
static Error CreateWin32(unsigned long err); static Error CreateWin32(unsigned long err);
static Error CreateHResult(long err); static Error CreateHResult(long err);
#endif #endif
// get code and description, e.g. "[0x00000002]: File not Found" // helpers for setting
SmallString GetCodeAndMessage() const; static void SetErrno(Error* errptr, int err);
void GetCodeAndMessage(String& dest) const; static void SetSocket(Error* errptr, int err);
static void SetString(Error* errptr, std::string description);
static void SetWin32(Error* errptr, unsigned long err);
static void SetHResult(Error* errptr, long err);
// operators
Error& operator=(const Error& e); Error& operator=(const Error& e);
Error& operator=(Error&& e);
bool operator==(const Error& e) const; bool operator==(const Error& e) const;
bool operator!=(const Error& e) const; bool operator!=(const Error& e) const;
private: private:
Type m_type = Type::None; Type m_type = Type::None;
union std::string m_description;
{
int none;
int errno_f; // renamed from errno to avoid conflicts with #define'd errnos.
int socketerr;
int user;
#ifdef _WIN32
unsigned long win32;
long hresult;
#endif
} m_error{};
StackString<16> m_code_string;
TinyString m_message;
}; };
} // namespace Common

View File

@ -3,9 +3,11 @@
#include "file_system.h" #include "file_system.h"
#include "assert.h" #include "assert.h"
#include "error.h"
#include "log.h" #include "log.h"
#include "path.h" #include "path.h"
#include "string_util.h" #include "string_util.h"
#include <algorithm> #include <algorithm>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@ -587,7 +589,7 @@ std::string Path::Combine(const std::string_view& base, const std::string_view&
return ret; return ret;
} }
std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode) std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode, Error* error)
{ {
#ifdef _WIN32 #ifdef _WIN32
const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename)); const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename));
@ -595,23 +597,34 @@ std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode)
if (!wfilename.empty() && !wmode.empty()) if (!wfilename.empty() && !wmode.empty())
{ {
std::FILE* fp; std::FILE* fp;
if (_wfopen_s(&fp, wfilename.c_str(), wmode.c_str()) != 0) const errno_t err = _wfopen_s(&fp, wfilename.c_str(), wmode.c_str());
if (err != 0)
{
Error::SetErrno(error, err);
return nullptr; return nullptr;
}
return fp; return fp;
} }
std::FILE* fp; std::FILE* fp;
if (fopen_s(&fp, filename, mode) != 0) const errno_t err = fopen_s(&fp, filename, mode);
if (err != 0)
{
Error::SetErrno(error, err);
return nullptr; return nullptr;
}
return fp; return fp;
#else #else
return std::fopen(filename, mode); std::FILE* fp = std::fopen(filename, mode);
if (!fp)
Error::SetErrno(error, errno);
return fp;
#endif #endif
} }
int FileSystem::OpenFDFile(const char* filename, int flags, int mode) int FileSystem::OpenFDFile(const char* filename, int flags, int mode, Error* error)
{ {
#ifdef _WIN32 #ifdef _WIN32
const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename)); const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename));
@ -620,18 +633,21 @@ int FileSystem::OpenFDFile(const char* filename, int flags, int mode)
return -1; return -1;
#else #else
return open(filename, flags, mode); const int fd = open(filename, flags, mode);
if (fd < 0)
Error::SetErrno(error, errno);
return fd;
#endif #endif
} }
#endif #endif
FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, const char* mode) FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, const char* mode, Error* error)
{ {
return ManagedCFilePtr(OpenCFile(filename, mode), [](std::FILE* fp) { std::fclose(fp); }); return ManagedCFilePtr(OpenCFile(filename, mode, error));
} }
std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode) std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error)
{ {
#ifdef _WIN32 #ifdef _WIN32
const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename)); const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename));
@ -661,16 +677,20 @@ std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, F
if (fp) if (fp)
return fp; return fp;
Error::SetErrno(error, errno);
return nullptr; return nullptr;
#else #else
return std::fopen(filename, mode); std::FILE* fp = std::fopen(filename, mode);
if (!fp)
Error::SetErrno(error, errno);
return fp;
#endif #endif
} }
FileSystem::ManagedCFilePtr FileSystem::OpenManagedSharedCFile(const char* filename, const char* mode, FileSystem::ManagedCFilePtr FileSystem::OpenManagedSharedCFile(const char* filename, const char* mode,
FileShareMode share_mode) FileShareMode share_mode, Error* error)
{ {
return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode), [](std::FILE* fp) { std::fclose(fp); }); return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode, error));
} }
int FileSystem::FSeek64(std::FILE* fp, s64 offset, int whence) int FileSystem::FSeek64(std::FILE* fp, s64 offset, int whence)

View File

@ -1,8 +1,10 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once #pragma once
#include "types.h" #include "types.h"
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
#include <memory> #include <memory>
@ -11,6 +13,8 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <vector> #include <vector>
class Error;
#ifdef _WIN32 #ifdef _WIN32
#define FS_OSPATH_SEPARATOR_CHARACTER '\\' #define FS_OSPATH_SEPARATOR_CHARACTER '\\'
#define FS_OSPATH_SEPARATOR_STR "\\" #define FS_OSPATH_SEPARATOR_STR "\\"
@ -87,15 +91,25 @@ bool DeleteFile(const char* path);
/// Rename file /// Rename file
bool RenamePath(const char* OldPath, const char* NewPath); bool RenamePath(const char* OldPath, const char* NewPath);
/// Deleter functor for managed file pointers
struct FileDeleter
{
ALWAYS_INLINE void operator()(std::FILE* fp)
{
if (fp)
std::fclose(fp);
}
};
/// open files /// open files
using ManagedCFilePtr = std::unique_ptr<std::FILE, void (*)(std::FILE*)>; using ManagedCFilePtr = std::unique_ptr<std::FILE, FileDeleter>;
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode); ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* error = nullptr);
std::FILE* OpenCFile(const char* filename, const char* mode); std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr);
int FSeek64(std::FILE* fp, s64 offset, int whence); int FSeek64(std::FILE* fp, s64 offset, int whence);
s64 FTell64(std::FILE* fp); s64 FTell64(std::FILE* fp);
s64 FSize64(std::FILE* fp); s64 FSize64(std::FILE* fp);
int OpenFDFile(const char* filename, int flags, int mode); int OpenFDFile(const char* filename, int flags, int mode, Error* error = nullptr);
/// Sharing modes for OpenSharedCFile(). /// Sharing modes for OpenSharedCFile().
enum class FileShareMode enum class FileShareMode
@ -108,8 +122,9 @@ enum class FileShareMode
/// Opens a file in shareable mode (where other processes can access it concurrently). /// Opens a file in shareable mode (where other processes can access it concurrently).
/// Only has an effect on Windows systems. /// Only has an effect on Windows systems.
ManagedCFilePtr OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode); ManagedCFilePtr OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode,
std::FILE* OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode); Error* error = nullptr);
std::FILE* OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error = nullptr);
/// Abstracts a POSIX file lock. /// Abstracts a POSIX file lock.
#ifndef _WIN32 #ifndef _WIN32

View File

@ -38,7 +38,7 @@ static s32 GetFreeFileHandle()
} }
const s32 index = static_cast<s32>(s_files.size()); const s32 index = static_cast<s32>(s_files.size());
s_files.emplace_back(nullptr, [](std::FILE*) {}); s_files.emplace_back(nullptr, FileSystem::FileDeleter());
return index; return index;
} }

View File

@ -1142,7 +1142,7 @@ bool System::BootSystem(SystemBootParameters parameters)
Host::OnSystemStarting(); Host::OnSystemStarting();
// Load CD image up and detect region. // Load CD image up and detect region.
Common::Error error; Error error;
std::unique_ptr<CDImage> disc; std::unique_ptr<CDImage> disc;
DiscRegion disc_region = DiscRegion::NonPS1; DiscRegion disc_region = DiscRegion::NonPS1;
std::string exe_boot; std::string exe_boot;
@ -1172,7 +1172,7 @@ bool System::BootSystem(SystemBootParameters parameters)
if (!disc) if (!disc)
{ {
Host::ReportErrorAsync("Error", fmt::format("Failed to load CD image '{}': {}", Host::ReportErrorAsync("Error", fmt::format("Failed to load CD image '{}': {}",
Path::GetFileName(parameters.filename), error.GetCodeAndMessage())); Path::GetFileName(parameters.filename), error.GetDescription()));
s_state = State::Shutdown; s_state = State::Shutdown;
Host::OnSystemDestroyed(); Host::OnSystemDestroyed();
return false; return false;
@ -1209,9 +1209,9 @@ bool System::BootSystem(SystemBootParameters parameters)
// Switch subimage. // Switch subimage.
if (disc && parameters.media_playlist_index != 0 && !disc->SwitchSubImage(parameters.media_playlist_index, &error)) if (disc && parameters.media_playlist_index != 0 && !disc->SwitchSubImage(parameters.media_playlist_index, &error))
{ {
Host::ReportFormattedErrorAsync("Error", "Failed to switch to subimage %u in '%s': %s", Host::ReportErrorAsync("Error",
parameters.media_playlist_index, parameters.filename.c_str(), fmt::format("Failed to switch to subimage {] in '{}': {}", parameters.media_playlist_index,
error.GetCodeAndMessage().GetCharArray()); parameters.filename, error.GetDescription()));
s_state = State::Shutdown; s_state = State::Shutdown;
Host::OnSystemDestroyed(); Host::OnSystemDestroyed();
return false; return false;
@ -2137,7 +2137,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u
return false; return false;
} }
Common::Error error; Error error;
std::string media_filename; std::string media_filename;
std::unique_ptr<CDImage> media; std::unique_ptr<CDImage> media;
if (header.media_filename_length > 0) if (header.media_filename_length > 0)
@ -2166,7 +2166,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u
30.0f, 30.0f,
Host::TranslateString("OSDMessage", "Failed to open CD image from save state '%s': %s. Using " Host::TranslateString("OSDMessage", "Failed to open CD image from save state '%s': %s. Using "
"existing image '%s', this may result in instability."), "existing image '%s', this may result in instability."),
media_filename.c_str(), error.GetCodeAndMessage().GetCharArray(), old_media->GetFileName().c_str()); media_filename.c_str(), error.GetDescription().c_str(), old_media->GetFileName().c_str());
media = std::move(old_media); media = std::move(old_media);
header.media_subimage_index = media->GetCurrentSubImage(); header.media_subimage_index = media->GetCurrentSubImage();
} }
@ -2174,7 +2174,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u
{ {
Host::ReportFormattedErrorAsync( Host::ReportFormattedErrorAsync(
"Error", Host::TranslateString("System", "Failed to open CD image '%s' used by save state: %s."), "Error", Host::TranslateString("System", "Failed to open CD image '%s' used by save state: %s."),
media_filename.c_str(), error.GetCodeAndMessage().GetCharArray()); media_filename.c_str(), error.GetDescription().c_str());
return false; return false;
} }
} }
@ -2193,7 +2193,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u
Host::ReportFormattedErrorAsync( Host::ReportFormattedErrorAsync(
"Error", "Error",
Host::TranslateString("System", "Failed to switch to subimage %u in CD image '%s' used by save state: %s."), Host::TranslateString("System", "Failed to switch to subimage %u in CD image '%s' used by save state: %s."),
header.media_subimage_index + 1u, media_filename.c_str(), error.GetCodeAndMessage().GetCharArray()); header.media_subimage_index + 1u, media_filename.c_str(), error.GetDescription().c_str());
return false; return false;
} }
else else
@ -3081,12 +3081,12 @@ std::string System::GetMediaFileName()
bool System::InsertMedia(const char* path) bool System::InsertMedia(const char* path)
{ {
Common::Error error; Error error;
std::unique_ptr<CDImage> image = CDImage::Open(path, g_settings.cdrom_load_image_patches, &error); 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."),
path, error.GetCodeAndMessage().GetCharArray()); path, error.GetDescription().c_str());
return false; return false;
} }
@ -3272,12 +3272,12 @@ bool System::SwitchMediaSubImage(u32 index)
std::unique_ptr<CDImage> image = CDROM::RemoveMedia(true); std::unique_ptr<CDImage> image = CDROM::RemoveMedia(true);
Assert(image); Assert(image);
Common::Error error; Error error;
if (!image->SwitchSubImage(index, &error)) if (!image->SwitchSubImage(index, &error))
{ {
Host::AddFormattedOSDMessage(10.0f, Host::AddFormattedOSDMessage(10.0f,
Host::TranslateString("OSDMessage", "Failed to switch to subimage %u in '%s': %s."), Host::TranslateString("OSDMessage", "Failed to switch to subimage %u in '%s': %s."),
index + 1u, image->GetFileName().c_str(), error.GetCodeAndMessage().GetCharArray()); index + 1u, image->GetFileName().c_str(), error.GetDescription().c_str());
const DiscRegion region = GetRegionForImage(image.get()); const DiscRegion region = GetRegionForImage(image.get());
CDROM::InsertMedia(std::move(image), region); CDROM::InsertMedia(std::move(image), region);

View File

@ -21,7 +21,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, bool allow_patches, Common::Error* error) std::unique_ptr<CDImage> CDImage::Open(const char* filename, bool allow_patches, Error* error)
{ {
const char* extension; const char* extension;
@ -94,10 +94,7 @@ std::unique_ptr<CDImage> CDImage::Open(const char* filename, bool allow_patches,
{ {
image = CDImage::OverlayPPFPatch(ppf_filename.c_str(), std::move(image)); image = CDImage::OverlayPPFPatch(ppf_filename.c_str(), std::move(image));
if (!image) if (!image)
{ Error::SetString(error, fmt::format("Failed to apply ppf patch from '{}'.", ppf_filename));
if (error)
error->SetFormattedMessage("Failed to apply ppf patch from '%s'.", ppf_filename.c_str());
}
} }
} }
@ -343,7 +340,7 @@ u32 CDImage::GetCurrentSubImage() const
return 0; return 0;
} }
bool CDImage::SwitchSubImage(u32 index, Common::Error* error) bool CDImage::SwitchSubImage(u32 index, Error* error)
{ {
return false; return false;
} }

View File

@ -11,9 +11,7 @@
#include <tuple> #include <tuple>
#include <vector> #include <vector>
namespace Common {
class Error; class Error;
}
class CDImage class CDImage
{ {
@ -220,15 +218,15 @@ 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, bool allow_patches, Common::Error* error); static std::unique_ptr<CDImage> Open(const char* filename, bool allow_patches, Error* error);
static std::unique_ptr<CDImage> OpenBinImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenBinImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenCueSheetImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenCueSheetImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenCHDImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenCHDImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenEcmImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenEcmImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenMdsImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenMdsImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenPBPImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenPBPImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenM3uImage(const char* filename, bool apply_patches, Common::Error* error); static std::unique_ptr<CDImage> OpenM3uImage(const char* filename, bool apply_patches, Error* error);
static std::unique_ptr<CDImage> OpenDeviceImage(const char* filename, Common::Error* error); static std::unique_ptr<CDImage> OpenDeviceImage(const char* filename, 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);
static std::unique_ptr<CDImage> OverlayPPFPatch(const char* filename, std::unique_ptr<CDImage> parent_image, static std::unique_ptr<CDImage> OverlayPPFPatch(const char* filename, std::unique_ptr<CDImage> parent_image,
@ -341,7 +339,7 @@ public:
virtual u32 GetCurrentSubImage() const; virtual u32 GetCurrentSubImage() const;
// Changes the current sub-image. If this fails, the image state is unchanged. // Changes the current sub-image. If this fails, the image state is unchanged.
virtual bool SwitchSubImage(u32 index, Common::Error* error); virtual bool SwitchSubImage(u32 index, Error* error);
// Retrieve sub-image metadata. // Retrieve sub-image metadata.
virtual std::string GetSubImageMetadata(u32 index, const std::string_view& type) const; virtual std::string GetSubImageMetadata(u32 index, const std::string_view& type) const;

View File

@ -15,7 +15,7 @@ public:
CDImageBin(); CDImageBin();
~CDImageBin() override; ~CDImageBin() override;
bool Open(const char* filename, Common::Error* error); bool Open(const char* filename, 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;
@ -38,7 +38,7 @@ CDImageBin::~CDImageBin()
std::fclose(m_fp); std::fclose(m_fp);
} }
bool CDImageBin::Open(const char* filename, Common::Error* error) bool CDImageBin::Open(const char* filename, Error* error)
{ {
m_filename = filename; m_filename = filename;
m_fp = FileSystem::OpenCFile(filename, "rb"); m_fp = FileSystem::OpenCFile(filename, "rb");
@ -136,7 +136,7 @@ bool CDImageBin::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i
return true; return true;
} }
std::unique_ptr<CDImage> CDImage::OpenBinImage(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenBinImage(const char* filename, Error* error)
{ {
std::unique_ptr<CDImageBin> image = std::make_unique<CDImageBin>(); std::unique_ptr<CDImageBin> image = std::make_unique<CDImageBin>();
if (!image->Open(filename, error)) if (!image->Open(filename, error))

View File

@ -59,7 +59,7 @@ public:
CDImageCHD(); CDImageCHD();
~CDImageCHD() override; ~CDImageCHD() override;
bool Open(const char* filename, Common::Error* error); bool Open(const char* filename, 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;
@ -77,7 +77,7 @@ private:
MAX_PARENTS = 32 // Surely someone wouldn't be insane enough to go beyond this... MAX_PARENTS = 32 // Surely someone wouldn't be insane enough to go beyond this...
}; };
chd_file* OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Common::Error* error, u32 recursion_level); chd_file* OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level);
bool ReadHunk(u32 hunk_index); bool ReadHunk(u32 hunk_index);
chd_file* m_chd = nullptr; chd_file* m_chd = nullptr;
@ -100,8 +100,7 @@ CDImageCHD::~CDImageCHD()
chd_close(m_chd); chd_close(m_chd);
} }
chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Common::Error* error, chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level)
u32 recursion_level)
{ {
chd_file* chd; chd_file* chd;
chd_error err = chd_open_file(fp.get(), CHD_OPEN_READ | CHD_OPEN_TRANSFER_FILE, nullptr, &chd); chd_error err = chd_open_file(fp.get(), CHD_OPEN_READ | CHD_OPEN_TRANSFER_FILE, nullptr, &chd);
@ -114,16 +113,14 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr
else if (err != CHDERR_REQUIRES_PARENT) else if (err != CHDERR_REQUIRES_PARENT)
{ {
Log_ErrorPrintf("Failed to open CHD '%s': %s", filename, chd_error_string(err)); Log_ErrorPrintf("Failed to open CHD '%s': %s", filename, chd_error_string(err));
if (error) Error::SetString(error, chd_error_string(err));
error->SetMessage(chd_error_string(err));
return nullptr; return nullptr;
} }
if (recursion_level >= MAX_PARENTS) if (recursion_level >= MAX_PARENTS)
{ {
Log_ErrorPrintf("Failed to open CHD '%s': Too many parent files", filename); Log_ErrorPrintf("Failed to open CHD '%s': Too many parent files", filename);
if (error) Error::SetString(error, "Too many parent files");
error->SetMessage("Too many parent files");
return nullptr; return nullptr;
} }
@ -133,8 +130,7 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr
if (err != CHDERR_NONE) if (err != CHDERR_NONE)
{ {
Log_ErrorPrintf("Failed to read CHD header '%s': %s", filename, chd_error_string(err)); Log_ErrorPrintf("Failed to read CHD header '%s': %s", filename, chd_error_string(err));
if (error) Error::SetString(error, chd_error_string(err));
error->SetMessage(chd_error_string(err));
return nullptr; return nullptr;
} }
@ -163,15 +159,16 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr
// Match! Open this one. // Match! Open this one.
if ((parent_chd = OpenCHD(fd.FileName.c_str(), std::move(parent_fp), error, recursion_level + 1)) != nullptr) if ((parent_chd = OpenCHD(fd.FileName.c_str(), std::move(parent_fp), error, recursion_level + 1)) != nullptr)
{ {
Log_DevPrintf(fmt::format("Found parent CHD '{}' for '{}'.", Path::GetFileName(fd.FileName), Path::GetFileName(filename)).c_str()); Log_DevPrintf(
fmt::format("Found parent CHD '{}' for '{}'.", Path::GetFileName(fd.FileName), Path::GetFileName(filename))
.c_str());
break; break;
} }
} }
if (!parent_chd) if (!parent_chd)
{ {
Log_ErrorPrintf("Failed to open CHD '%s': Failed to find parent CHD, it must be in the same directory.", filename); Log_ErrorPrintf("Failed to open CHD '%s': Failed to find parent CHD, it must be in the same directory.", filename);
if (error) Error::SetString(error, "Failed to find parent CHD, it must be in the same directory.");
error->SetMessage("Failed to find parent CHD, it must be in the same directory.");
return nullptr; return nullptr;
} }
@ -180,8 +177,7 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr
if (err != CHDERR_NONE) if (err != CHDERR_NONE)
{ {
Log_ErrorPrintf("Failed to open CHD '%s': %s", filename, chd_error_string(err)); Log_ErrorPrintf("Failed to open CHD '%s': %s", filename, chd_error_string(err));
if (error) Error::SetString(error, chd_error_string(err));
error->SetMessage(chd_error_string(err));
return nullptr; return nullptr;
} }
@ -190,7 +186,7 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr
return chd; return chd;
} }
bool CDImageCHD::Open(const char* filename, Common::Error* error) bool CDImageCHD::Open(const char* filename, Error* error)
{ {
auto fp = FileSystem::OpenManagedSharedCFile(filename, "rb", FileSystem::FileShareMode::DenyWrite); auto fp = FileSystem::OpenManagedSharedCFile(filename, "rb", FileSystem::FileShareMode::DenyWrite);
if (!fp) if (!fp)
@ -211,9 +207,8 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
if ((m_hunk_size % CHD_CD_SECTOR_DATA_SIZE) != 0) 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); Log_ErrorPrintf("Hunk size (%u) is not a multiple of %u", m_hunk_size, CHD_CD_SECTOR_DATA_SIZE);
if (error) Error::SetString(error, fmt::format("Hunk size ({}) is not a multiple of {}", m_hunk_size,
error->SetFormattedMessage("Hunk size (%u) is not a multiple of %u", m_hunk_size, CHD_CD_SECTOR_DATA_SIZE); static_cast<u32>(CHD_CD_SECTOR_DATA_SIZE)));
return false; return false;
} }
@ -244,9 +239,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
&pregap_frames, pgtype_str, pgsub_str, &postgap_frames) != 8) &pregap_frames, pgtype_str, pgsub_str, &postgap_frames) != 8)
{ {
Log_ErrorPrintf("Invalid track v2 metadata: '%s'", metadata_str); Log_ErrorPrintf("Invalid track v2 metadata: '%s'", metadata_str);
if (error) Error::SetString(error, fmt::format("Invalid track v2 metadata: '{}'", metadata_str));
error->SetFormattedMessage("Invalid track v2 metadata: '%s'", metadata_str);
return false; return false;
} }
} }
@ -264,9 +257,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
if (std::sscanf(metadata_str, CDROM_TRACK_METADATA_FORMAT, &track_num, type_str, subtype_str, &frames) != 4) 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); Log_ErrorPrintf("Invalid track metadata: '%s'", metadata_str);
if (error) Error::SetString(error, fmt::format("Invalid track v2 metadata: '{}'", metadata_str));
error->SetFormattedMessage("Invalid track v2 metadata: '%s'", metadata_str);
return false; return false;
} }
} }
@ -275,12 +266,8 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
{ {
Log_ErrorPrintf("Incorrect track number at index %d, expected %d got %d", num_tracks, (num_tracks + 1), Log_ErrorPrintf("Incorrect track number at index %d, expected %d got %d", num_tracks, (num_tracks + 1),
track_num); track_num);
if (error) Error::SetString(error, fmt::format("Incorrect track number at index {}, expected {} got {}", num_tracks,
{ (num_tracks + 1), track_num));
error->SetFormattedMessage("Incorrect track number at index %d, expected %d got %d", num_tracks,
(num_tracks + 1), track_num);
}
return false; return false;
} }
@ -288,9 +275,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
if (!mode.has_value()) if (!mode.has_value())
{ {
Log_ErrorPrintf("Invalid track mode: '%s'", type_str); Log_ErrorPrintf("Invalid track mode: '%s'", type_str);
if (error) Error::SetString(error, fmt::format("Invalid track mode: '{}'", type_str));
error->SetFormattedMessage("Invalid track mode: '%s'", type_str);
return false; return false;
} }
@ -321,9 +306,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
if (pregap_frames > frames) if (pregap_frames > frames)
{ {
Log_ErrorPrintf("Pregap length %u exceeds track length %u", pregap_frames, frames); Log_ErrorPrintf("Pregap length %u exceeds track length %u", pregap_frames, frames);
if (error) Error::SetString(error, fmt::format("Pregap length {} exceeds track length {}", pregap_frames, frames));
error->SetFormattedMessage("Pregap length %u exceeds track length %u", pregap_frames, frames);
return false; return false;
} }
@ -368,9 +351,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
if (m_tracks.empty()) if (m_tracks.empty())
{ {
Log_ErrorPrintf("File '%s' contains no tracks", filename); Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error) Error::SetString(error, fmt::format("File '{}' contains no tracks", filename));
error->SetFormattedMessage("File '%s' contains no tracks", filename);
return false; return false;
} }
@ -497,7 +478,7 @@ bool CDImageCHD::ReadHunk(u32 hunk_index)
return true; return true;
} }
std::unique_ptr<CDImage> CDImage::OpenCHDImage(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenCHDImage(const char* filename, Error* error)
{ {
std::unique_ptr<CDImageCHD> image = std::make_unique<CDImageCHD>(); std::unique_ptr<CDImageCHD> image = std::make_unique<CDImageCHD>();
if (!image->Open(filename, error)) if (!image->Open(filename, error))

View File

@ -3,16 +3,21 @@
#include "cd_image.h" #include "cd_image.h"
#include "cd_subchannel_replacement.h" #include "cd_subchannel_replacement.h"
#include "cue_parser.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/error.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"
#include "cue_parser.h"
#include "fmt/format.h"
#include <algorithm> #include <algorithm>
#include <cerrno> #include <cerrno>
#include <cinttypes> #include <cinttypes>
#include <map> #include <map>
Log_SetChannel(CDImageCueSheet); Log_SetChannel(CDImageCueSheet);
class CDImageCueSheet : public CDImage class CDImageCueSheet : public CDImage
@ -21,7 +26,7 @@ public:
CDImageCueSheet(); CDImageCueSheet();
~CDImageCueSheet() override; ~CDImageCueSheet() override;
bool OpenAndParse(const char* filename, Common::Error* error); bool OpenAndParse(const char* filename, 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;
@ -48,7 +53,7 @@ CDImageCueSheet::~CDImageCueSheet()
std::for_each(m_files.begin(), m_files.end(), [](TrackFile& t) { std::fclose(t.file); }); std::for_each(m_files.begin(), m_files.end(), [](TrackFile& t) { std::fclose(t.file); });
} }
bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error) bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error)
{ {
std::FILE* fp = FileSystem::OpenCFile(filename, "rb"); std::FILE* fp = FileSystem::OpenCFile(filename, "rb");
if (!fp) if (!fp)
@ -94,7 +99,8 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error)
{ {
const std::string track_full_filename( const std::string track_full_filename(
!Path::IsAbsolute(track_filename) ? Path::BuildRelativePath(m_filename, track_filename) : track_filename); !Path::IsAbsolute(track_filename) ? Path::BuildRelativePath(m_filename, track_filename) : track_filename);
std::FILE* track_fp = FileSystem::OpenCFile(track_full_filename.c_str(), "rb"); Error track_error;
std::FILE* track_fp = FileSystem::OpenCFile(track_full_filename.c_str(), "rb", &track_error);
if (!track_fp && track_file_index == 0) if (!track_fp && track_file_index == 0)
{ {
// many users have bad cuesheets, or they're renamed the files without updating the cuesheet. // many users have bad cuesheets, or they're renamed the files without updating the cuesheet.
@ -110,14 +116,11 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error)
if (!track_fp) if (!track_fp)
{ {
Log_ErrorPrintf("Failed to open track filename '%s' (from '%s' and '%s'): errno %d", Log_ErrorPrintf("Failed to open track filename '%s' (from '%s' and '%s'): %s", track_full_filename.c_str(),
track_full_filename.c_str(), track_filename.c_str(), filename, errno); track_filename.c_str(), filename, track_error.GetDescription().c_str());
if (error) Error::SetString(error,
{ fmt::format("Failed to open track filename '{}' (from '{}' and '{}'): {}", track_full_filename,
error->SetFormattedMessage("Failed to open track filename '%s' (from '%s' and '%s'): errno %d", track_filename, filename, track_error.GetDescription()));
track_full_filename.c_str(), track_filename.c_str(), filename, errno);
}
return false; return false;
} }
@ -148,11 +151,8 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error)
{ {
Log_ErrorPrintf("Failed to open track %u in '%s': track start is out of range (%u vs %" PRIu64 ")", track_num, Log_ErrorPrintf("Failed to open track %u in '%s': track start is out of range (%u vs %" PRIu64 ")", track_num,
filename, track_start, file_size); filename, track_start, file_size);
if (error) Error::SetString(error, fmt::format("Failed to open track {} in '{}': track start is out of range ({} vs {}))",
{ track_num, filename, track_start, file_size));
error->SetFormattedMessage("Failed to open track %u in '%s': track start is out of range (%u vs %" PRIu64 ")",
track_num, filename, track_start, file_size);
}
return false; return false;
} }
@ -283,8 +283,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error)
if (m_tracks.empty()) if (m_tracks.empty())
{ {
Log_ErrorPrintf("File '%s' contains no tracks", filename); Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error) Error::SetString(error, fmt::format("File '{}' contains no tracks", filename));
error->SetFormattedMessage("File '%s' contains no tracks", filename);
return false; return false;
} }
@ -333,7 +332,7 @@ bool CDImageCueSheet::ReadSectorFromIndex(void* buffer, const Index& index, LBA
return true; return true;
} }
std::unique_ptr<CDImage> CDImage::OpenCueSheetImage(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenCueSheetImage(const char* filename, Error* error)
{ {
std::unique_ptr<CDImageCueSheet> image = std::make_unique<CDImageCueSheet>(); std::unique_ptr<CDImageCueSheet> image = std::make_unique<CDImageCueSheet>();
if (!image->OpenAndParse(filename, error)) if (!image->OpenAndParse(filename, error))

View File

@ -72,7 +72,7 @@ public:
CDImageDeviceWin32(); CDImageDeviceWin32();
~CDImageDeviceWin32() override; ~CDImageDeviceWin32() override;
bool Open(const char* filename, Common::Error* error); bool Open(const char* filename, 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;
@ -112,7 +112,7 @@ CDImageDeviceWin32::~CDImageDeviceWin32()
CloseHandle(m_hDevice); CloseHandle(m_hDevice);
} }
bool CDImageDeviceWin32::Open(const char* filename, Common::Error* error) bool CDImageDeviceWin32::Open(const char* filename, Error* error)
{ {
m_filename = filename; m_filename = filename;
m_hDevice = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, m_hDevice = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
@ -244,8 +244,7 @@ bool CDImageDeviceWin32::Open(const char* filename, Common::Error* error)
if (m_tracks.empty()) if (m_tracks.empty())
{ {
Log_ErrorPrintf("File '%s' contains no tracks", filename); Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error) Error::SetString(error, fmt::format("File '{}' contains no tracks", filename));
error->SetFormattedMessage("File '%s' contains no tracks", filename);
return false; return false;
} }
@ -270,9 +269,7 @@ bool CDImageDeviceWin32::Open(const char* filename, Common::Error* error)
if (!DetermineReadMode()) if (!DetermineReadMode())
{ {
Log_ErrorPrintf("Could not determine read mode"); Log_ErrorPrintf("Could not determine read mode");
if (error) Error::SetString(error, "Could not determine read mode");
error->SetMessage("Could not determine read mode");
return false; return false;
} }
@ -476,7 +473,7 @@ bool CDImageDeviceWin32::DetermineReadMode()
return false; return false;
} }
std::unique_ptr<CDImage> CDImage::OpenDeviceImage(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenDeviceImage(const char* filename, Error* error)
{ {
std::unique_ptr<CDImageDeviceWin32> image = std::make_unique<CDImageDeviceWin32>(); std::unique_ptr<CDImageDeviceWin32> image = std::make_unique<CDImageDeviceWin32>();
if (!image->Open(filename, error)) if (!image->Open(filename, error))
@ -528,7 +525,7 @@ bool CDImage::IsDeviceName(const char* filename)
#else #else
std::unique_ptr<CDImage> CDImage::OpenDeviceImage(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenDeviceImage(const char* filename, Error* error)
{ {
return {}; return {};
} }

View File

@ -164,7 +164,7 @@ public:
CDImageEcm(); CDImageEcm();
~CDImageEcm() override; ~CDImageEcm() override;
bool Open(const char* filename, Common::Error* error); bool Open(const char* filename, 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;
@ -224,7 +224,7 @@ CDImageEcm::~CDImageEcm()
std::fclose(m_fp); std::fclose(m_fp);
} }
bool CDImageEcm::Open(const char* filename, Common::Error* error) bool CDImageEcm::Open(const char* filename, Error* error)
{ {
m_filename = filename; m_filename = filename;
m_fp = FileSystem::OpenCFile(filename, "rb"); m_fp = FileSystem::OpenCFile(filename, "rb");
@ -253,9 +253,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error)
header[3] != 0) header[3] != 0)
{ {
Log_ErrorPrintf("Failed to read/invalid header"); Log_ErrorPrintf("Failed to read/invalid header");
if (error) Error::SetString(error, "Failed to read/invalid header");
error->SetMessage("Failed to read/invalid header");
return false; return false;
} }
@ -269,9 +267,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error)
if (bits == EOF) if (bits == EOF)
{ {
Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size());
if (error) Error::SetString(error, fmt::format("Unexpected EOF after {} chunks", m_data_map.size()));
error->SetFormattedMessage("Unexpected EOF after %zu chunks", m_data_map.size());
return false; return false;
} }
@ -285,9 +281,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error)
if (bits == EOF) if (bits == EOF)
{ {
Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size());
if (error) Error::SetString(error, fmt::format("Unexpected EOF after {} chunks", m_data_map.size()));
error->SetFormattedMessage("Unexpected EOF after %zu chunks", m_data_map.size());
return false; return false;
} }
@ -305,9 +299,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error)
if (count >= 0x80000000u) if (count >= 0x80000000u)
{ {
Log_ErrorPrintf("Corrupted header after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Corrupted header after %zu chunks", m_data_map.size());
if (error) Error::SetString(error, fmt::format("Corrupted header after {} chunks", m_data_map.size()));
error->SetFormattedMessage("Corrupted header after %zu chunks", m_data_map.size());
return false; return false;
} }
@ -324,8 +316,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error)
if (static_cast<s64>(file_offset) > file_size) if (static_cast<s64>(file_offset) > file_size)
{ {
Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size());
if (error) Error::SetString(error, fmt::format("Out of file bounds after {} chunks", m_data_map.size()));
error->SetFormattedMessage("Out of file bounds after %zu chunks", m_data_map.size());
} }
} }
} }
@ -342,8 +333,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error)
if (static_cast<s64>(file_offset) > file_size) if (static_cast<s64>(file_offset) > file_size)
{ {
Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size()); Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size());
if (error) Error::SetString(error, fmt::format("Out of file bounds after {} chunks", m_data_map.size()));
error->SetFormattedMessage("Out of file bounds after %zu chunks", m_data_map.size());
} }
} }
} }
@ -351,9 +341,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error)
if (std::fseek(m_fp, file_offset, SEEK_SET) != 0) 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()); Log_ErrorPrintf("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size());
if (error) Error::SetString(error, fmt::format("Failed to seek to offset {} after {} chunks", file_offset, m_data_map.size()));
error->SetFormattedMessage("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size());
return false; return false;
} }
} }
@ -361,9 +349,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error)
if (m_data_map.empty()) if (m_data_map.empty())
{ {
Log_ErrorPrintf("No data in image '%s'", filename); Log_ErrorPrintf("No data in image '%s'", filename);
if (error) Error::SetString(error, fmt::format("No data in image '{}'", filename));
error->SetFormattedMessage("No data in image '%s'", filename);
return false; return false;
} }
@ -549,7 +535,7 @@ bool CDImageEcm::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i
return true; return true;
} }
std::unique_ptr<CDImage> CDImage::OpenEcmImage(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenEcmImage(const char* filename, Error* error)
{ {
std::unique_ptr<CDImageEcm> image = std::make_unique<CDImageEcm>(); std::unique_ptr<CDImageEcm> image = std::make_unique<CDImageEcm>();
if (!image->Open(filename, error)) if (!image->Open(filename, error))

View File

@ -20,7 +20,7 @@ public:
CDImageM3u(); CDImageM3u();
~CDImageM3u() override; ~CDImageM3u() override;
bool Open(const char* path, bool apply_patches, Common::Error* Error); bool Open(const char* path, bool apply_patches, 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;
@ -29,7 +29,7 @@ public:
u32 GetSubImageCount() const override; u32 GetSubImageCount() const override;
u32 GetCurrentSubImage() const override; u32 GetCurrentSubImage() const override;
std::string GetSubImageMetadata(u32 index, const std::string_view& type) const override; std::string GetSubImageMetadata(u32 index, const std::string_view& type) const override;
bool SwitchSubImage(u32 index, Common::Error* error) override; bool SwitchSubImage(u32 index, Error* error) 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;
@ -52,7 +52,7 @@ CDImageM3u::CDImageM3u() = default;
CDImageM3u::~CDImageM3u() = default; CDImageM3u::~CDImageM3u() = default;
bool CDImageM3u::Open(const char* path, bool apply_patches, Common::Error* error) bool CDImageM3u::Open(const char* path, bool apply_patches, Error* error)
{ {
std::FILE* fp = FileSystem::OpenCFile(path, "rb"); std::FILE* fp = FileSystem::OpenCFile(path, "rb");
if (!fp) if (!fp)
@ -62,8 +62,7 @@ bool CDImageM3u::Open(const char* path, bool apply_patches, Common::Error* error
std::fclose(fp); std::fclose(fp);
if (!m3u_file.has_value() || m3u_file->empty()) if (!m3u_file.has_value() || m3u_file->empty())
{ {
if (error) Error::SetString(error, "Failed to read M3u file");
error->SetMessage("Failed to read M3u file");
return false; return false;
} }
@ -128,7 +127,7 @@ u32 CDImageM3u::GetCurrentSubImage() const
return m_current_image_index; return m_current_image_index;
} }
bool CDImageM3u::SwitchSubImage(u32 index, Common::Error* error) bool CDImageM3u::SwitchSubImage(u32 index, Error* error)
{ {
if (index >= m_entries.size()) if (index >= m_entries.size())
return false; return false;
@ -175,7 +174,7 @@ 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, bool apply_patches, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenM3uImage(const char* filename, bool apply_patches, Error* error)
{ {
std::unique_ptr<CDImageM3u> image = std::make_unique<CDImageM3u>(); std::unique_ptr<CDImageM3u> image = std::make_unique<CDImageM3u>();
if (!image->Open(filename, apply_patches, error)) if (!image->Open(filename, apply_patches, error))

View File

@ -39,7 +39,7 @@ public:
CDImageMds(); CDImageMds();
~CDImageMds() override; ~CDImageMds() override;
bool OpenAndParse(const char* filename, Common::Error* error); bool OpenAndParse(const char* filename, 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;
@ -61,15 +61,12 @@ CDImageMds::~CDImageMds()
std::fclose(m_mdf_file); std::fclose(m_mdf_file);
} }
bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) bool CDImageMds::OpenAndParse(const char* filename, Error* error)
{ {
std::FILE* mds_fp = FileSystem::OpenCFile(filename, "rb"); std::FILE* mds_fp = FileSystem::OpenCFile(filename, "rb", error);
if (!mds_fp) if (!mds_fp)
{ {
Log_ErrorPrintf("Failed to open mds '%s': errno %d", filename, errno); Log_ErrorPrintf("Failed to open mds '%s': errno %d", filename, errno);
if (error)
error->SetErrno(errno);
return false; return false;
} }
@ -78,20 +75,15 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if (!mds_data_opt.has_value() || mds_data_opt->size() < 0x54) if (!mds_data_opt.has_value() || mds_data_opt->size() < 0x54)
{ {
Log_ErrorPrintf("Failed to read mds file '%s'", filename); Log_ErrorPrintf("Failed to read mds file '%s'", filename);
if (error) Error::SetString(error, fmt::format("Failed to read mds file '{}'", filename));
error->SetFormattedMessage("Failed to read mds file '%s'", filename);
return false; return false;
} }
std::string mdf_filename(Path::ReplaceExtension(filename, "mdf")); std::string mdf_filename(Path::ReplaceExtension(filename, "mdf"));
m_mdf_file = FileSystem::OpenCFile(mdf_filename.c_str(), "rb"); m_mdf_file = FileSystem::OpenCFile(mdf_filename.c_str(), "rb", error);
if (!m_mdf_file) if (!m_mdf_file)
{ {
Log_ErrorPrintf("Failed to open mdf file '%s': errno %d", mdf_filename.c_str(), errno); 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; return false;
} }
@ -100,9 +92,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if (std::memcmp(&mds[0], expected_signature, sizeof(expected_signature) - 1) != 0) if (std::memcmp(&mds[0], expected_signature, sizeof(expected_signature) - 1) != 0)
{ {
Log_ErrorPrintf("Incorrect signature in '%s'", filename); Log_ErrorPrintf("Incorrect signature in '%s'", filename);
if (error) Error::SetString(error, fmt::format("Incorrect signature in '{}'", filename));
error->SetFormattedMessage("Incorrect signature in '%s'", filename);
return false; return false;
} }
@ -111,9 +101,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if ((session_offset + 24) > mds.size()) if ((session_offset + 24) > mds.size())
{ {
Log_ErrorPrintf("Invalid session offset in '%s'", filename); Log_ErrorPrintf("Invalid session offset in '%s'", filename);
if (error) Error::SetString(error, fmt::format("Invalid session offset in '{}'", filename));
error->SetFormattedMessage("Invalid session offset in '%s'", filename);
return false; return false;
} }
@ -124,9 +112,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if (track_count > 99 || track_offset >= mds.size()) if (track_count > 99 || track_offset >= mds.size())
{ {
Log_ErrorPrintf("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename); Log_ErrorPrintf("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename);
if (error) Error::SetString(error, fmt::format("Invalid track count/block offset {}/{} in '{}'", track_count, track_offset, filename));
error->SetFormattedMessage("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename);
return false; return false;
} }
@ -145,9 +131,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if ((track_offset + sizeof(TrackEntry)) > mds.size()) if ((track_offset + sizeof(TrackEntry)) > mds.size())
{ {
Log_ErrorPrintf("End of file in '%s' at track %u", filename, track_number); Log_ErrorPrintf("End of file in '%s' at track %u", filename, track_number);
if (error) Error::SetString(error, fmt::format("End of file in '{}' at track {}", filename, track_number));
error->SetFormattedMessage("End of file in '%s' at track %u", filename, track_number);
return false; return false;
} }
@ -158,9 +142,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if (PackedBCDToBinary(track.track_number) != track_number) if (PackedBCDToBinary(track.track_number) != track_number)
{ {
Log_ErrorPrintf("Unexpected track number 0x%02X in track %u", track.track_number, track_number); Log_ErrorPrintf("Unexpected track number 0x%02X in track %u", track.track_number, track_number);
if (error) Error::SetString(error, fmt::format("Unexpected track number 0x{:02X} in track {}", track.track_number, track_number));
error->SetFormattedMessage("Unexpected track number 0x%02X in track %u", track.track_number, track_number);
return false; return false;
} }
@ -171,9 +153,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if ((track.extra_offset + sizeof(u32) + sizeof(u32)) > mds.size()) if ((track.extra_offset + sizeof(u32) + sizeof(u32)) > mds.size())
{ {
Log_ErrorPrintf("Invalid extra offset %u in track %u", track.extra_offset, track_number); Log_ErrorPrintf("Invalid extra offset %u in track %u", track.extra_offset, track_number);
if (error) Error::SetString(error, fmt::format("Invalid extra offset {} in track {}", track.extra_offset, track_number));
error->SetFormattedMessage("Invalid extra offset %u in track %u", track.extra_offset, track_number);
return false; return false;
} }
@ -196,9 +176,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if (track_pregap > track_start_lba) if (track_pregap > track_start_lba)
{ {
Log_ErrorPrintf("Track pregap %u is too large for start lba %u", 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::SetString(error, fmt::format("Track pregap {} is too large for start lba {}", track_pregap, track_start_lba));
error->SetFormattedMessage("Track pregap %u is too large for start lba %u", track_pregap, track_start_lba);
return false; return false;
} }
@ -247,9 +225,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if (m_tracks.empty()) if (m_tracks.empty())
{ {
Log_ErrorPrintf("File '%s' contains no tracks", filename); Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error) Error::SetString(error, fmt::format("File '{}' contains no tracks", filename));
error->SetFormattedMessage("File '%s' contains no tracks", filename);
return false; return false;
} }
@ -297,7 +273,7 @@ bool CDImageMds::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i
return true; return true;
} }
std::unique_ptr<CDImage> CDImage::OpenMdsImage(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenMdsImage(const char* filename, Error* error)
{ {
std::unique_ptr<CDImageMds> image = std::make_unique<CDImageMds>(); std::unique_ptr<CDImageMds> image = std::make_unique<CDImageMds>();
if (!image->OpenAndParse(filename, error)) if (!image->OpenAndParse(filename, error))

View File

@ -27,7 +27,7 @@ public:
CDImagePBP() = default; CDImagePBP() = default;
~CDImagePBP() override; ~CDImagePBP() override;
bool Open(const char* filename, Common::Error* error); bool Open(const char* filename, 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;
@ -35,7 +35,7 @@ public:
bool HasSubImages() const override; bool HasSubImages() const override;
u32 GetSubImageCount() const override; u32 GetSubImageCount() const override;
u32 GetCurrentSubImage() const override; u32 GetCurrentSubImage() const override;
bool SwitchSubImage(u32 index, Common::Error* error) override; bool SwitchSubImage(u32 index, Error* error) override;
std::string GetMetadata(const std::string_view& type) const override; std::string GetMetadata(const std::string_view& type) const override;
std::string GetSubImageMetadata(u32 index, const std::string_view& type) const override; std::string GetSubImageMetadata(u32 index, const std::string_view& type) const override;
@ -61,12 +61,12 @@ private:
bool LoadSFOIndexTable(); bool LoadSFOIndexTable();
bool LoadSFOTable(); bool LoadSFOTable();
bool IsValidEboot(Common::Error* error); bool IsValidEboot(Error* error);
bool InitDecompressionStream(); bool InitDecompressionStream();
bool DecompressBlock(const BlockInfo& block_info); bool DecompressBlock(const BlockInfo& block_info);
bool OpenDisc(u32 index, Common::Error* error); bool OpenDisc(u32 index, Error* error);
static const std::string* LookupStringSFOTableEntry(const char* key, const SFOTable& table); static const std::string* LookupStringSFOTableEntry(const char* key, const SFOTable& table);
@ -277,7 +277,7 @@ bool CDImagePBP::LoadSFOTable()
return true; return true;
} }
bool CDImagePBP::IsValidEboot(Common::Error* error) bool CDImagePBP::IsValidEboot(Error* error)
{ {
// Check some fields to make sure this is a valid PS1 EBOOT.PBP // Check some fields to make sure this is a valid PS1 EBOOT.PBP
@ -288,16 +288,14 @@ bool CDImagePBP::IsValidEboot(Common::Error* error)
if (!std::holds_alternative<u32>(data_value) || std::get<u32>(data_value) != 1) if (!std::holds_alternative<u32>(data_value) || std::get<u32>(data_value) != 1)
{ {
Log_ErrorPrint("Invalid BOOTABLE value"); Log_ErrorPrint("Invalid BOOTABLE value");
if (error) Error::SetString(error, "Invalid BOOTABLE value");
error->SetMessage("Invalid BOOTABLE value");
return false; return false;
} }
} }
else else
{ {
Log_ErrorPrint("No BOOTABLE value found"); Log_ErrorPrint("No BOOTABLE value found");
if (error) Error::SetString(error, "No BOOTABLE value found");
error->SetMessage("No BOOTABLE value found");
return false; return false;
} }
@ -308,23 +306,21 @@ bool CDImagePBP::IsValidEboot(Common::Error* error)
if (!std::holds_alternative<std::string>(data_value) || std::get<std::string>(data_value) != "ME") if (!std::holds_alternative<std::string>(data_value) || std::get<std::string>(data_value) != "ME")
{ {
Log_ErrorPrint("Invalid CATEGORY value"); Log_ErrorPrint("Invalid CATEGORY value");
if (error) Error::SetString(error, "Invalid CATEGORY value");
error->SetMessage("Invalid CATEGORY value");
return false; return false;
} }
} }
else else
{ {
Log_ErrorPrint("No CATEGORY value found"); Log_ErrorPrint("No CATEGORY value found");
if (error) Error::SetString(error, "No CATEGORY value found");
error->SetMessage("No CATEGORY value found");
return false; return false;
} }
return true; return true;
} }
bool CDImagePBP::Open(const char* filename, Common::Error* error) bool CDImagePBP::Open(const char* filename, Error* error)
{ {
if (!EndianHelper::HostIsLittleEndian()) if (!EndianHelper::HostIsLittleEndian())
{ {
@ -347,8 +343,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (!LoadPBPHeader()) if (!LoadPBPHeader())
{ {
Log_ErrorPrint("Failed to load PBP header"); Log_ErrorPrint("Failed to load PBP header");
if (error) Error::SetString(error, "Failed to load PBP header");
error->SetMessage("Failed to load PBP header");
return false; return false;
} }
@ -356,8 +351,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (!LoadSFOHeader()) if (!LoadSFOHeader())
{ {
Log_ErrorPrint("Failed to load SFO header"); Log_ErrorPrint("Failed to load SFO header");
if (error) Error::SetString(error, "Failed to load SFO header");
error->SetMessage("Failed to load SFO header");
return false; return false;
} }
@ -365,8 +359,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (!LoadSFOIndexTable()) if (!LoadSFOIndexTable())
{ {
Log_ErrorPrint("Failed to load SFO index table"); Log_ErrorPrint("Failed to load SFO index table");
if (error) Error::SetString(error, "Failed to load SFO index table");
error->SetMessage("Failed to load SFO index table");
return false; return false;
} }
@ -374,8 +367,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (!LoadSFOTable()) if (!LoadSFOTable())
{ {
Log_ErrorPrint("Failed to load SFO table"); Log_ErrorPrint("Failed to load SFO table");
if (error) Error::SetString(error, "Failed to load SFO table");
error->SetMessage("Failed to load SFO table");
return false; return false;
} }
@ -412,9 +404,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (disc_table[0] == 0x44475000) // "\0PGD" if (disc_table[0] == 0x44475000) // "\0PGD"
{ {
Log_ErrorPrintf("Encrypted PBP images are not supported, skipping %s", m_filename.c_str()); Log_ErrorPrintf("Encrypted PBP images are not supported, skipping %s", m_filename.c_str());
if (error) Error::SetString(error, "Encrypted PBP images are not supported");
error->SetMessage("Encrypted PBP images are not supported");
return false; return false;
} }
@ -442,13 +432,12 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
return OpenDisc(0, error); return OpenDisc(0, error);
} }
bool CDImagePBP::OpenDisc(u32 index, Common::Error* error) bool CDImagePBP::OpenDisc(u32 index, Error* error)
{ {
if (index >= m_disc_offsets.size()) if (index >= m_disc_offsets.size())
{ {
Log_ErrorPrintf("File does not contain disc %u", index + 1); Log_ErrorPrintf("File does not contain disc %u", index + 1);
if (error) Error::SetString(error, fmt::format("File does not contain disc {}", index + 1));
error->SetMessage(TinyString::FromFormat("File does not contain disc %u", index + 1));
return false; return false;
} }
@ -484,9 +473,7 @@ bool CDImagePBP::OpenDisc(u32 index, Common::Error* error)
if (pgd_magic == 0x44475000) // "\0PGD" if (pgd_magic == 0x44475000) // "\0PGD"
{ {
Log_ErrorPrintf("Encrypted PBP images are not supported, skipping %s", m_filename.c_str()); Log_ErrorPrintf("Encrypted PBP images are not supported, skipping %s", m_filename.c_str());
if (error) Error::SetString(error, "Encrypted PBP images are not supported");
error->SetMessage("Encrypted PBP images are not supported");
return false; return false;
} }
@ -867,7 +854,7 @@ u32 CDImagePBP::GetCurrentSubImage() const
return m_current_disc; return m_current_disc;
} }
bool CDImagePBP::SwitchSubImage(u32 index, Common::Error* error) bool CDImagePBP::SwitchSubImage(u32 index, Error* error)
{ {
if (index >= m_disc_offsets.size()) if (index >= m_disc_offsets.size())
return false; return false;
@ -895,7 +882,7 @@ std::string CDImagePBP::GetSubImageMetadata(u32 index, const std::string_view& t
return CDImage::GetSubImageMetadata(index, type); return CDImage::GetSubImageMetadata(index, type);
} }
std::unique_ptr<CDImage> CDImage::OpenPBPImage(const char* filename, Common::Error* error) std::unique_ptr<CDImage> CDImage::OpenPBPImage(const char* filename, Error* error)
{ {
std::unique_ptr<CDImagePBP> image = std::make_unique<CDImagePBP>(); std::unique_ptr<CDImagePBP> image = std::make_unique<CDImagePBP>();
if (!image->Open(filename, error)) if (!image->Open(filename, error))

View File

@ -45,7 +45,7 @@ Track* File::GetMutableTrack(u32 n)
return nullptr; return nullptr;
} }
bool File::Parse(std::FILE* fp, Common::Error* error) bool File::Parse(std::FILE* fp, Error* error)
{ {
char line[1024]; char line[1024];
u32 line_number = 1; u32 line_number = 1;
@ -66,7 +66,7 @@ bool File::Parse(std::FILE* fp, Common::Error* error)
return true; return true;
} }
void File::SetError(u32 line_number, Common::Error* error, const char* format, ...) void File::SetError(u32 line_number, Error* error, const char* format, ...)
{ {
std::va_list ap; std::va_list ap;
SmallString str; SmallString str;
@ -75,9 +75,7 @@ void File::SetError(u32 line_number, Common::Error* error, const char* format, .
va_end(ap); va_end(ap);
Log_ErrorPrintf("Cue parse error at line %u: %s", line_number, str.GetCharArray()); Log_ErrorPrintf("Cue parse error at line %u: %s", line_number, str.GetCharArray());
Error::SetString(error, fmt::format("Cue parse error at line {}: {}", line_number, str));
if (error)
error->SetFormattedMessage("Cue parse error at line %u: %s", line_number, str.GetCharArray());
} }
std::string_view File::GetToken(const char*& line) std::string_view File::GetToken(const char*& line)
@ -166,7 +164,7 @@ std::optional<MSF> File::GetMSF(const std::string_view& token)
return ret; return ret;
} }
bool File::ParseLine(const char* line, u32 line_number, Common::Error* error) bool File::ParseLine(const char* line, u32 line_number, Error* error)
{ {
const std::string_view command(GetToken(line)); const std::string_view command(GetToken(line));
if (command.empty()) if (command.empty())
@ -210,7 +208,7 @@ bool File::ParseLine(const char* line, u32 line_number, Common::Error* error)
return false; return false;
} }
bool File::HandleFileCommand(const char* line, u32 line_number, Common::Error* error) bool File::HandleFileCommand(const char* line, u32 line_number, Error* error)
{ {
const std::string_view filename(GetToken(line)); const std::string_view filename(GetToken(line));
const std::string_view mode(GetToken(line)); const std::string_view mode(GetToken(line));
@ -232,7 +230,7 @@ bool File::HandleFileCommand(const char* line, u32 line_number, Common::Error* e
return true; return true;
} }
bool File::HandleTrackCommand(const char* line, u32 line_number, Common::Error* error) bool File::HandleTrackCommand(const char* line, u32 line_number, Error* error)
{ {
if (!CompleteLastTrack(line_number, error)) if (!CompleteLastTrack(line_number, error))
return false; return false;
@ -288,7 +286,7 @@ bool File::HandleTrackCommand(const char* line, u32 line_number, Common::Error*
return true; return true;
} }
bool File::HandleIndexCommand(const char* line, u32 line_number, Common::Error* error) bool File::HandleIndexCommand(const char* line, u32 line_number, Error* error)
{ {
if (!m_current_track.has_value()) if (!m_current_track.has_value())
{ {
@ -334,7 +332,7 @@ bool File::HandleIndexCommand(const char* line, u32 line_number, Common::Error*
return true; return true;
} }
bool File::HandlePregapCommand(const char* line, u32 line_number, Common::Error* error) bool File::HandlePregapCommand(const char* line, u32 line_number, Error* error)
{ {
if (!m_current_track.has_value()) if (!m_current_track.has_value())
{ {
@ -366,7 +364,7 @@ bool File::HandlePregapCommand(const char* line, u32 line_number, Common::Error*
return true; return true;
} }
bool File::HandleFlagCommand(const char* line, u32 line_number, Common::Error* error) bool File::HandleFlagCommand(const char* line, u32 line_number, Error* error)
{ {
if (!m_current_track.has_value()) if (!m_current_track.has_value())
{ {
@ -395,7 +393,7 @@ bool File::HandleFlagCommand(const char* line, u32 line_number, Common::Error* e
return true; return true;
} }
bool File::CompleteLastTrack(u32 line_number, Common::Error* error) bool File::CompleteLastTrack(u32 line_number, Error* error)
{ {
if (!m_current_track.has_value()) if (!m_current_track.has_value())
return true; return true;
@ -436,7 +434,7 @@ bool File::CompleteLastTrack(u32 line_number, Common::Error* error)
return true; return true;
} }
bool File::SetTrackLengths(u32 line_number, Common::Error* error) bool File::SetTrackLengths(u32 line_number, Error* error)
{ {
for (const Track& track : m_tracks) for (const Track& track : m_tracks)
{ {

View File

@ -60,26 +60,26 @@ public:
const Track* GetTrack(u32 n) const; const Track* GetTrack(u32 n) const;
bool Parse(std::FILE* fp, Common::Error* error); bool Parse(std::FILE* fp, Error* error);
private: private:
Track* GetMutableTrack(u32 n); Track* GetMutableTrack(u32 n);
void SetError(u32 line_number, Common::Error* error, const char* format, ...); void SetError(u32 line_number, Error* error, const char* format, ...);
static std::string_view GetToken(const char*& line); static std::string_view GetToken(const char*& line);
static std::optional<MSF> GetMSF(const std::string_view& token); static std::optional<MSF> GetMSF(const std::string_view& token);
bool ParseLine(const char* line, u32 line_number, Common::Error* error); bool ParseLine(const char* line, u32 line_number, Error* error);
bool HandleFileCommand(const char* line, u32 line_number, Common::Error* error); bool HandleFileCommand(const char* line, u32 line_number, Error* error);
bool HandleTrackCommand(const char* line, u32 line_number, Common::Error* error); bool HandleTrackCommand(const char* line, u32 line_number, Error* error);
bool HandleIndexCommand(const char* line, u32 line_number, Common::Error* error); bool HandleIndexCommand(const char* line, u32 line_number, Error* error);
bool HandlePregapCommand(const char* line, u32 line_number, Common::Error* error); bool HandlePregapCommand(const char* line, u32 line_number, Error* error);
bool HandleFlagCommand(const char* line, u32 line_number, Common::Error* error); bool HandleFlagCommand(const char* line, u32 line_number, Error* error);
bool CompleteLastTrack(u32 line_number, Common::Error* error); bool CompleteLastTrack(u32 line_number, Error* error);
bool SetTrackLengths(u32 line_number, Common::Error* error); bool SetTrackLengths(u32 line_number, Error* error);
std::vector<Track> m_tracks; std::vector<Track> m_tracks;
std::optional<std::string> m_current_file; std::optional<std::string> m_current_file;