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)
#include "error.h"
#include "string_util.h"
#include <cstdlib>
#include <cstring>
#include <type_traits>
// Platform-specific includes
#include "fmt/format.h"
#if defined(_WIN32)
#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
namespace Common {
Error::Error() = default;
Error::Error() : m_type(Type::None)
{
m_error.none = 0;
}
Error::Error(const Error& c) = default;
Error::Error(const Error& c)
{
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(Error&& e) = default;
Error::~Error() = default;
void Error::Clear()
{
m_type = Type::None;
m_error.none = 0;
m_code_string.Clear();
m_message.Clear();
m_description = {};
}
void Error::SetErrno(int err)
{
m_type = Type::Errno;
m_error.errno_f = err;
m_code_string.Format("%i", err);
#ifdef _MSC_VER
strerror_s(m_message.GetWriteableCharArray(), m_message.GetBufferSize(), err);
m_message.UpdateSize();
#else
const char* message = std::strerror(err);
if (message)
m_message = message;
char buf[128];
if (strerror_s(buf, sizeof(buf), err) != 0)
m_description = fmt::format("errno {}: {}", err, buf);
else
m_message = StaticString("<Could not get error message>");
#endif
}
void Error::SetSocket(int err)
{
// Socket errors are win32 errors on windows
#ifdef _WIN32
SetWin32(err);
m_description = fmt::format("errno {}: <Could not get error message>", err);
#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
}
void Error::SetMessage(const char* msg)
void Error::SetErrno(Error* errptr, int err)
{
m_type = Type::User;
m_error.user = 0;
m_code_string.Clear();
m_message = msg;
if (errptr)
errptr->SetErrno(err);
}
void Error::SetUser(int err, const char* msg)
void Error::SetString(std::string description)
{
m_type = Type::User;
m_error.user = err;
m_code_string.Format("%d", err);
m_message = msg;
m_description = std::move(description);
}
void Error::SetUser(const char* code, const char* message)
void Error::SetString(Error* errptr, std::string description)
{
m_type = Type::User;
m_error.user = 0;
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);
if (errptr)
errptr->SetString(std::move(description));
}
#ifdef _WIN32
void Error::SetWin32(unsigned long err)
{
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(),
m_message.GetWritableBufferSize(), NULL);
WCHAR buf[128];
const DWORD r = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_USER_DEFAULT, buf,
static_cast<DWORD>(std::size(buf)), nullptr);
if (r > 0)
{
m_message.Resize(r);
m_message.RStrip();
m_description =
fmt::format("Win32 Error {}: {}", err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
}
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)
{
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(),
m_message.GetWritableBufferSize(), NULL);
WCHAR buf[128];
const DWORD r = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_USER_DEFAULT, buf,
static_cast<DWORD>(std::size(buf)), nullptr);
if (r > 0)
{
m_message.Resize(r);
m_message.RStrip();
m_description =
fmt::format("HRESULT {:08X}: {}", err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
}
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
// 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 ret;
ret.Clear();
return ret;
return Error();
}
Error Error::CreateErrno(int err)
@ -193,70 +151,10 @@ Error Error::CreateSocket(int err)
return ret;
}
Error Error::CreateMessage(const char* msg)
Error Error::CreateString(std::string description)
{
Error ret;
ret.SetMessage(msg);
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);
ret.SetString(std::move(description));
return ret;
}
@ -277,86 +175,16 @@ Error Error::CreateHResult(long err)
#endif
Error& Error::operator=(const Error& e)
{
m_type = e.m_type;
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;
}
Error& Error::operator=(const Error& e) = default;
Error& Error::operator=(Error&& e) = default;
bool Error::operator==(const Error& e) const
{
switch (m_type)
{
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;
return (m_type == e.m_type && m_description == e.m_description);
}
bool Error::operator!=(const Error& e) const
{
switch (m_type)
{
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
return (m_type != e.m_type || m_description != e.m_description);
}

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)
#pragma once
#include "string.h"
#include "types.h"
namespace Common {
#include <string>
// this class provides enough storage room for all of these types
class Error
{
public:
Error();
Error(const Error& e);
Error(Error&& e);
~Error();
enum class Type
{
None = 0, // Set by default constructor, returns 'No Error'.
Errno = 1, // Error that is set by system functions, such as open().
Socket = 2, // Error that is set by socket functions, such as socket(). On Unix this is the same as errno.
User = 3, // When translated, will return 'User Error %u' if no message is specified.
Win32 = 4, // Error that is returned by some Win32 functions, such as RegOpenKeyEx. Also used by other APIs through
// GetLastError().
HResult = 5, // Error that is returned by Win32 COM methods, e.g. S_OK.
None = 0,
Errno = 1,
Socket = 2,
User = 3,
Win32 = 4,
HResult = 5,
};
ALWAYS_INLINE Type GetType() const { return m_type; }
ALWAYS_INLINE int GetErrnoCode() const { return m_error.errno_f; }
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
ALWAYS_INLINE const std::string& GetDescription() const { return m_description; }
// 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();
/// Error that is set by system functions, such as open().
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 SetMessage(const char* msg);
void SetFormattedMessage(const char* format, ...) printflike(2, 3);
void SetUser(int err, const char* msg);
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);
/// Set both description and message.
void SetString(std::string description);
#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);
/// Error that is returned by Win32 COM methods, e.g. S_OK.
void SetHResult(long err);
#endif
// constructors
static Error CreateNone();
static Error CreateErrno(int err);
static Error CreateSocket(int err);
static Error CreateMessage(const char* msg);
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);
static Error CreateString(std::string description);
#ifdef _WIN32
static Error CreateWin32(unsigned long err);
static Error CreateHResult(long err);
#endif
// get code and description, e.g. "[0x00000002]: File not Found"
SmallString GetCodeAndMessage() const;
void GetCodeAndMessage(String& dest) const;
// helpers for setting
static void SetErrno(Error* errptr, int err);
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=(Error&& e);
bool operator==(const Error& e) const;
bool operator!=(const Error& e) const;
private:
Type m_type = Type::None;
union
{
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;
std::string m_description;
};
} // namespace Common

View File

@ -3,9 +3,11 @@
#include "file_system.h"
#include "assert.h"
#include "error.h"
#include "log.h"
#include "path.h"
#include "string_util.h"
#include <algorithm>
#include <cstdlib>
#include <cstring>
@ -587,7 +589,7 @@ std::string Path::Combine(const std::string_view& base, const std::string_view&
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
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())
{
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 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 fp;
#else
return std::fopen(filename, mode);
std::FILE* fp = std::fopen(filename, mode);
if (!fp)
Error::SetErrno(error, errno);
return fp;
#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
const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename));
@ -620,18 +633,21 @@ int FileSystem::OpenFDFile(const char* filename, int flags, int mode)
return -1;
#else
return open(filename, flags, mode);
const int fd = open(filename, flags, mode);
if (fd < 0)
Error::SetErrno(error, errno);
return fd;
#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
const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename));
@ -661,16 +677,20 @@ std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, F
if (fp)
return fp;
Error::SetErrno(error, errno);
return nullptr;
#else
return std::fopen(filename, mode);
std::FILE* fp = std::fopen(filename, mode);
if (!fp)
Error::SetErrno(error, errno);
return fp;
#endif
}
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)

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)
#pragma once
#include "types.h"
#include <cstdio>
#include <ctime>
#include <memory>
@ -11,6 +13,8 @@
#include <sys/stat.h>
#include <vector>
class Error;
#ifdef _WIN32
#define FS_OSPATH_SEPARATOR_CHARACTER '\\'
#define FS_OSPATH_SEPARATOR_STR "\\"
@ -87,15 +91,25 @@ bool DeleteFile(const char* path);
/// Rename file
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
using ManagedCFilePtr = std::unique_ptr<std::FILE, void (*)(std::FILE*)>;
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode);
std::FILE* OpenCFile(const char* filename, const char* mode);
using ManagedCFilePtr = std::unique_ptr<std::FILE, FileDeleter>;
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* error = nullptr);
std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr);
int FSeek64(std::FILE* fp, s64 offset, int whence);
s64 FTell64(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().
enum class FileShareMode
@ -108,8 +122,9 @@ enum class FileShareMode
/// Opens a file in shareable mode (where other processes can access it concurrently).
/// Only has an effect on Windows systems.
ManagedCFilePtr OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode);
std::FILE* OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode);
ManagedCFilePtr OpenManagedSharedCFile(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.
#ifndef _WIN32

View File

@ -38,7 +38,7 @@ static s32 GetFreeFileHandle()
}
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;
}

View File

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

View File

@ -21,7 +21,7 @@ u32 CDImage::GetBytesPerSector(TrackMode 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;
@ -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));
if (!image)
{
if (error)
error->SetFormattedMessage("Failed to apply ppf patch from '%s'.", ppf_filename.c_str());
}
Error::SetString(error, fmt::format("Failed to apply ppf patch from '{}'.", ppf_filename));
}
}
@ -343,7 +340,7 @@ u32 CDImage::GetCurrentSubImage() const
return 0;
}
bool CDImage::SwitchSubImage(u32 index, Common::Error* error)
bool CDImage::SwitchSubImage(u32 index, Error* error)
{
return false;
}

View File

@ -11,9 +11,7 @@
#include <tuple>
#include <vector>
namespace Common {
class Error;
}
class CDImage
{
@ -220,15 +218,15 @@ public:
static bool IsDeviceName(const char* filename);
// Opening disc image.
static std::unique_ptr<CDImage> Open(const char* filename, bool allow_patches, Common::Error* error);
static std::unique_ptr<CDImage> OpenBinImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage> 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> OpenM3uImage(const char* filename, bool apply_patches, Common::Error* error);
static std::unique_ptr<CDImage> OpenDeviceImage(const char* filename, Common::Error* error);
static std::unique_ptr<CDImage> Open(const char* filename, bool allow_patches, Error* error);
static std::unique_ptr<CDImage> OpenBinImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenCueSheetImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenCHDImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenEcmImage(const char* filename, Error* error);
static std::unique_ptr<CDImage> OpenMdsImage(const char* filename, 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, Error* error);
static std::unique_ptr<CDImage> OpenDeviceImage(const char* filename, Error* error);
static std::unique_ptr<CDImage>
CreateMemoryImage(CDImage* image, ProgressCallback* progress = ProgressCallback::NullProgressCallback);
static std::unique_ptr<CDImage> OverlayPPFPatch(const char* filename, std::unique_ptr<CDImage> parent_image,
@ -341,7 +339,7 @@ public:
virtual u32 GetCurrentSubImage() const;
// 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.
virtual std::string GetSubImageMetadata(u32 index, const std::string_view& type) const;

View File

@ -15,7 +15,7 @@ public:
CDImageBin();
~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 HasNonStandardSubchannel() const override;
@ -38,7 +38,7 @@ CDImageBin::~CDImageBin()
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_fp = FileSystem::OpenCFile(filename, "rb");
@ -136,7 +136,7 @@ bool CDImageBin::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i
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>();
if (!image->Open(filename, error))

View File

@ -59,7 +59,7 @@ public:
CDImageCHD();
~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 HasNonStandardSubchannel() const override;
@ -77,7 +77,7 @@ private:
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);
chd_file* m_chd = nullptr;
@ -100,8 +100,7 @@ CDImageCHD::~CDImageCHD()
chd_close(m_chd);
}
chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Common::Error* error,
u32 recursion_level)
chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level)
{
chd_file* 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)
{
Log_ErrorPrintf("Failed to open CHD '%s': %s", filename, chd_error_string(err));
if (error)
error->SetMessage(chd_error_string(err));
Error::SetString(error, chd_error_string(err));
return nullptr;
}
if (recursion_level >= MAX_PARENTS)
{
Log_ErrorPrintf("Failed to open CHD '%s': Too many parent files", filename);
if (error)
error->SetMessage("Too many parent files");
Error::SetString(error, "Too many parent files");
return nullptr;
}
@ -133,8 +130,7 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr
if (err != CHDERR_NONE)
{
Log_ErrorPrintf("Failed to read CHD header '%s': %s", filename, chd_error_string(err));
if (error)
error->SetMessage(chd_error_string(err));
Error::SetString(error, chd_error_string(err));
return nullptr;
}
@ -163,15 +159,16 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr
// Match! Open this one.
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;
}
}
if (!parent_chd)
{
Log_ErrorPrintf("Failed to open CHD '%s': Failed to find parent CHD, it must be in the same directory.", filename);
if (error)
error->SetMessage("Failed to find parent CHD, it must be in the same directory.");
Error::SetString(error, "Failed to find parent CHD, it must be in the same directory.");
return nullptr;
}
@ -180,8 +177,7 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr
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));
Error::SetString(error, chd_error_string(err));
return nullptr;
}
@ -190,7 +186,7 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr
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);
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)
{
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);
Error::SetString(error, fmt::format("Hunk size ({}) is not a multiple of {}", m_hunk_size,
static_cast<u32>(CHD_CD_SECTOR_DATA_SIZE)));
return false;
}
@ -244,9 +239,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
&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);
Error::SetString(error, fmt::format("Invalid track v2 metadata: '{}'", metadata_str));
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)
{
Log_ErrorPrintf("Invalid track metadata: '%s'", metadata_str);
if (error)
error->SetFormattedMessage("Invalid track v2 metadata: '%s'", metadata_str);
Error::SetString(error, fmt::format("Invalid track v2 metadata: '{}'", metadata_str));
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),
track_num);
if (error)
{
error->SetFormattedMessage("Incorrect track number at index %d, expected %d got %d", num_tracks,
(num_tracks + 1), track_num);
}
Error::SetString(error, fmt::format("Incorrect track number at index {}, expected {} got {}", num_tracks,
(num_tracks + 1), track_num));
return false;
}
@ -288,9 +275,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
if (!mode.has_value())
{
Log_ErrorPrintf("Invalid track mode: '%s'", type_str);
if (error)
error->SetFormattedMessage("Invalid track mode: '%s'", type_str);
Error::SetString(error, fmt::format("Invalid track mode: '{}'", type_str));
return false;
}
@ -321,9 +306,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
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);
Error::SetString(error, fmt::format("Pregap length {} exceeds track length {}", pregap_frames, frames));
return false;
}
@ -368,9 +351,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error)
if (m_tracks.empty())
{
Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error)
error->SetFormattedMessage("File '%s' contains no tracks", filename);
Error::SetString(error, fmt::format("File '{}' contains no tracks", filename));
return false;
}
@ -497,7 +478,7 @@ bool CDImageCHD::ReadHunk(u32 hunk_index)
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>();
if (!image->Open(filename, error))

View File

@ -3,16 +3,21 @@
#include "cd_image.h"
#include "cd_subchannel_replacement.h"
#include "cue_parser.h"
#include "common/assert.h"
#include "common/error.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/path.h"
#include "cue_parser.h"
#include "fmt/format.h"
#include <algorithm>
#include <cerrno>
#include <cinttypes>
#include <map>
Log_SetChannel(CDImageCueSheet);
class CDImageCueSheet : public CDImage
@ -21,7 +26,7 @@ public:
CDImageCueSheet();
~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 HasNonStandardSubchannel() const override;
@ -48,7 +53,7 @@ CDImageCueSheet::~CDImageCueSheet()
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");
if (!fp)
@ -94,7 +99,8 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error)
{
const std::string track_full_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)
{
// 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)
{
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);
}
Log_ErrorPrintf("Failed to open track filename '%s' (from '%s' and '%s'): %s", track_full_filename.c_str(),
track_filename.c_str(), filename, track_error.GetDescription().c_str());
Error::SetString(error,
fmt::format("Failed to open track filename '{}' (from '{}' and '{}'): {}", track_full_filename,
track_filename, filename, track_error.GetDescription()));
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,
filename, track_start, file_size);
if (error)
{
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);
}
Error::SetString(error, fmt::format("Failed to open track {} in '{}': track start is out of range ({} vs {}))",
track_num, filename, track_start, file_size));
return false;
}
@ -283,8 +283,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error)
if (m_tracks.empty())
{
Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error)
error->SetFormattedMessage("File '%s' contains no tracks", filename);
Error::SetString(error, fmt::format("File '{}' contains no tracks", filename));
return false;
}
@ -333,7 +332,7 @@ bool CDImageCueSheet::ReadSectorFromIndex(void* buffer, const Index& index, LBA
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>();
if (!image->OpenAndParse(filename, error))

View File

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

View File

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

View File

@ -20,7 +20,7 @@ public:
CDImageM3u();
~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 HasNonStandardSubchannel() const override;
@ -29,7 +29,7 @@ public:
u32 GetSubImageCount() const override;
u32 GetCurrentSubImage() 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:
bool ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index) override;
@ -52,7 +52,7 @@ 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");
if (!fp)
@ -62,8 +62,7 @@ bool CDImageM3u::Open(const char* path, bool apply_patches, Common::Error* error
std::fclose(fp);
if (!m3u_file.has_value() || m3u_file->empty())
{
if (error)
error->SetMessage("Failed to read M3u file");
Error::SetString(error, "Failed to read M3u file");
return false;
}
@ -128,7 +127,7 @@ u32 CDImageM3u::GetCurrentSubImage() const
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())
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);
}
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>();
if (!image->Open(filename, apply_patches, error))

View File

@ -39,7 +39,7 @@ public:
CDImageMds();
~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 HasNonStandardSubchannel() const override;
@ -61,15 +61,12 @@ CDImageMds::~CDImageMds()
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)
{
Log_ErrorPrintf("Failed to open mds '%s': errno %d", filename, errno);
if (error)
error->SetErrno(errno);
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)
{
Log_ErrorPrintf("Failed to read mds file '%s'", filename);
if (error)
error->SetFormattedMessage("Failed to read mds file '%s'", filename);
Error::SetString(error, fmt::format("Failed to read mds file '{}'", filename));
return false;
}
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)
{
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;
}
@ -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)
{
Log_ErrorPrintf("Incorrect signature in '%s'", filename);
if (error)
error->SetFormattedMessage("Incorrect signature in '%s'", filename);
Error::SetString(error, fmt::format("Incorrect signature in '{}'", filename));
return false;
}
@ -111,9 +101,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if ((session_offset + 24) > mds.size())
{
Log_ErrorPrintf("Invalid session offset in '%s'", filename);
if (error)
error->SetFormattedMessage("Invalid session offset in '%s'", filename);
Error::SetString(error, fmt::format("Invalid session offset in '{}'", filename));
return false;
}
@ -124,9 +112,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
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);
Error::SetString(error, fmt::format("Invalid track count/block offset {}/{} in '{}'", track_count, track_offset, filename));
return false;
}
@ -145,9 +131,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
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);
Error::SetString(error, fmt::format("End of file in '{}' at track {}", filename, track_number));
return false;
}
@ -158,9 +142,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
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);
Error::SetString(error, fmt::format("Unexpected track number 0x{:02X} in track {}", track.track_number, track_number));
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())
{
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);
Error::SetString(error, fmt::format("Invalid extra offset {} in track {}", track.extra_offset, track_number));
return false;
}
@ -196,9 +176,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
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);
Error::SetString(error, fmt::format("Track pregap {} is too large for start lba {}", track_pregap, track_start_lba));
return false;
}
@ -247,9 +225,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error)
if (m_tracks.empty())
{
Log_ErrorPrintf("File '%s' contains no tracks", filename);
if (error)
error->SetFormattedMessage("File '%s' contains no tracks", filename);
Error::SetString(error, fmt::format("File '{}' contains no tracks", filename));
return false;
}
@ -297,7 +273,7 @@ bool CDImageMds::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i
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>();
if (!image->OpenAndParse(filename, error))

View File

@ -27,7 +27,7 @@ public:
CDImagePBP() = default;
~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 HasNonStandardSubchannel() const override;
@ -35,7 +35,7 @@ public:
bool HasSubImages() const override;
u32 GetSubImageCount() 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 GetSubImageMetadata(u32 index, const std::string_view& type) const override;
@ -61,12 +61,12 @@ private:
bool LoadSFOIndexTable();
bool LoadSFOTable();
bool IsValidEboot(Common::Error* error);
bool IsValidEboot(Error* error);
bool InitDecompressionStream();
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);
@ -277,7 +277,7 @@ bool CDImagePBP::LoadSFOTable()
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
@ -288,16 +288,14 @@ bool CDImagePBP::IsValidEboot(Common::Error* error)
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");
Error::SetString(error, "Invalid BOOTABLE value");
return false;
}
}
else
{
Log_ErrorPrint("No BOOTABLE value found");
if (error)
error->SetMessage("No BOOTABLE value found");
Error::SetString(error, "No BOOTABLE value found");
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")
{
Log_ErrorPrint("Invalid CATEGORY value");
if (error)
error->SetMessage("Invalid CATEGORY value");
Error::SetString(error, "Invalid CATEGORY value");
return false;
}
}
else
{
Log_ErrorPrint("No CATEGORY value found");
if (error)
error->SetMessage("No CATEGORY value found");
Error::SetString(error, "No CATEGORY value found");
return false;
}
return true;
}
bool CDImagePBP::Open(const char* filename, Common::Error* error)
bool CDImagePBP::Open(const char* filename, Error* error)
{
if (!EndianHelper::HostIsLittleEndian())
{
@ -347,8 +343,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (!LoadPBPHeader())
{
Log_ErrorPrint("Failed to load PBP header");
if (error)
error->SetMessage("Failed to load PBP header");
Error::SetString(error, "Failed to load PBP header");
return false;
}
@ -356,8 +351,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (!LoadSFOHeader())
{
Log_ErrorPrint("Failed to load SFO header");
if (error)
error->SetMessage("Failed to load SFO header");
Error::SetString(error, "Failed to load SFO header");
return false;
}
@ -365,8 +359,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (!LoadSFOIndexTable())
{
Log_ErrorPrint("Failed to load SFO index table");
if (error)
error->SetMessage("Failed to load SFO index table");
Error::SetString(error, "Failed to load SFO index table");
return false;
}
@ -374,8 +367,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (!LoadSFOTable())
{
Log_ErrorPrint("Failed to load SFO table");
if (error)
error->SetMessage("Failed to load SFO table");
Error::SetString(error, "Failed to load SFO table");
return false;
}
@ -412,9 +404,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error)
if (disc_table[0] == 0x44475000) // "\0PGD"
{
Log_ErrorPrintf("Encrypted PBP images are not supported, skipping %s", m_filename.c_str());
if (error)
error->SetMessage("Encrypted PBP images are not supported");
Error::SetString(error, "Encrypted PBP images are not supported");
return false;
}
@ -442,13 +432,12 @@ bool CDImagePBP::Open(const char* filename, Common::Error* 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())
{
Log_ErrorPrintf("File does not contain disc %u", index + 1);
if (error)
error->SetMessage(TinyString::FromFormat("File does not contain disc %u", index + 1));
Error::SetString(error, fmt::format("File does not contain disc {}", index + 1));
return false;
}
@ -484,9 +473,7 @@ bool CDImagePBP::OpenDisc(u32 index, Common::Error* error)
if (pgd_magic == 0x44475000) // "\0PGD"
{
Log_ErrorPrintf("Encrypted PBP images are not supported, skipping %s", m_filename.c_str());
if (error)
error->SetMessage("Encrypted PBP images are not supported");
Error::SetString(error, "Encrypted PBP images are not supported");
return false;
}
@ -867,7 +854,7 @@ u32 CDImagePBP::GetCurrentSubImage() const
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())
return false;
@ -895,7 +882,7 @@ std::string CDImagePBP::GetSubImageMetadata(u32 index, const std::string_view& t
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>();
if (!image->Open(filename, error))

View File

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

View File

@ -60,26 +60,26 @@ public:
const Track* GetTrack(u32 n) const;
bool Parse(std::FILE* fp, Common::Error* error);
bool Parse(std::FILE* fp, Error* error);
private:
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::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 HandleTrackCommand(const char* line, u32 line_number, Common::Error* error);
bool HandleIndexCommand(const char* line, u32 line_number, Common::Error* error);
bool HandlePregapCommand(const char* line, u32 line_number, Common::Error* error);
bool HandleFlagCommand(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, Error* error);
bool HandleIndexCommand(const char* line, u32 line_number, Error* error);
bool HandlePregapCommand(const char* line, u32 line_number, Error* error);
bool HandleFlagCommand(const char* line, u32 line_number, Error* error);
bool CompleteLastTrack(u32 line_number, Common::Error* error);
bool SetTrackLengths(u32 line_number, Common::Error* error);
bool CompleteLastTrack(u32 line_number, Error* error);
bool SetTrackLengths(u32 line_number, Error* error);
std::vector<Track> m_tracks;
std::optional<std::string> m_current_file;