From a9959bcd62f2cfd305e467aa159dfd9c3d1b4921 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 1 Oct 2023 01:20:53 +1000 Subject: [PATCH] CDVD: Report open errors to host --- common/Pcsx2Defs.h | 5 - pcsx2/AsyncFileReader.h | 125 ++++++++++----------- pcsx2/CDVD/BlockdumpFileReader.cpp | 38 ++++--- pcsx2/CDVD/CDVDcommon.cpp | 44 ++++---- pcsx2/CDVD/CDVDcommon.h | 98 ++++++++--------- pcsx2/CDVD/CDVDdiscReader.cpp | 60 ++++++----- pcsx2/CDVD/CDVDdiscReader.h | 9 +- pcsx2/CDVD/CDVDdiscThread.cpp | 30 +++--- pcsx2/CDVD/CDVDisoReader.cpp | 59 +++++----- pcsx2/CDVD/ChdFileReader.cpp | 16 +-- pcsx2/CDVD/ChdFileReader.h | 6 +- pcsx2/CDVD/CsoFileReader.cpp | 121 +++++++++++---------- pcsx2/CDVD/CsoFileReader.h | 80 ++++++-------- pcsx2/CDVD/Darwin/IOCtlSrc.cpp | 11 +- pcsx2/CDVD/GzippedFileReader.cpp | 138 ++++++++++++++---------- pcsx2/CDVD/GzippedFileReader.h | 82 +++++++------- pcsx2/CDVD/InputIsoFile.cpp | 13 +-- pcsx2/CDVD/IsoFileFormats.h | 12 ++- pcsx2/CDVD/IsoHasher.cpp | 5 +- pcsx2/CDVD/Linux/IOCtlSrc.cpp | 11 +- pcsx2/CDVD/ThreadedFileReader.cpp | 14 +-- pcsx2/CDVD/ThreadedFileReader.h | 22 ++-- pcsx2/CDVD/Windows/IOCtlSrc.cpp | 11 +- pcsx2/Darwin/DarwinFlatFileReader.cpp | 31 +++--- pcsx2/GameList.cpp | 10 +- pcsx2/Linux/LnxFlatFileReader.cpp | 25 ++--- pcsx2/MultipartFileReader.cpp | 9 +- pcsx2/VMManager.cpp | 20 ++-- pcsx2/windows/FlatFileReaderWindows.cpp | 34 +++--- 29 files changed, 592 insertions(+), 547 deletions(-) diff --git a/common/Pcsx2Defs.h b/common/Pcsx2Defs.h index d11e2e001c..7bbad01916 100644 --- a/common/Pcsx2Defs.h +++ b/common/Pcsx2Defs.h @@ -97,8 +97,6 @@ static constexpr unsigned int __pagemask = __pagesize - 1; #define likely(x) (!!(x)) #define unlikely(x) (!!(x)) - #define CALLBACK __stdcall - #else // -------------------------------------------------------------------------------------- @@ -110,9 +108,6 @@ static constexpr unsigned int __pagemask = __pagesize - 1; // SysV ABI passes vector parameters through registers unconditionally. #ifndef _WIN32 #define __vectorcall - #define CALLBACK - #else - #define CALLBACK __attribute__((stdcall)) #endif // Inlining note: GCC needs ((unused)) attributes defined on inlined functions to suppress diff --git a/pcsx2/AsyncFileReader.h b/pcsx2/AsyncFileReader.h index f0a68c5b66..8b9a05923b 100644 --- a/pcsx2/AsyncFileReader.h +++ b/pcsx2/AsyncFileReader.h @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2014 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -16,54 +16,56 @@ #pragma once #ifdef _WIN32 -# include "common/RedtapeWindows.h" +#include "common/RedtapeWindows.h" #elif defined(__linux__) -# include +#include #elif defined(__POSIX__) -# include +#include #endif #include #include +class Error; + class AsyncFileReader { protected: - AsyncFileReader() : m_dataoffset(0), m_blocksize(0) {} + AsyncFileReader() + : m_dataoffset(0) + , m_blocksize(0) + { + } std::string m_filename; - int m_dataoffset; - uint m_blocksize; + u32 m_dataoffset; + u32 m_blocksize; public: - virtual ~AsyncFileReader() {}; + virtual ~AsyncFileReader(){}; - virtual bool Open(std::string fileName)=0; + virtual bool Open(std::string filename, Error* error) = 0; - virtual int ReadSync(void* pBuffer, uint sector, uint count)=0; + virtual int ReadSync(void* pBuffer, u32 sector, u32 count) = 0; - virtual void BeginRead(void* pBuffer, uint sector, uint count)=0; - virtual int FinishRead(void)=0; - virtual void CancelRead(void)=0; + virtual void BeginRead(void* pBuffer, u32 sector, u32 count) = 0; + virtual int FinishRead() = 0; + virtual void CancelRead() = 0; - virtual void Close(void)=0; + virtual void Close() = 0; - virtual uint GetBlockCount(void) const=0; + virtual u32 GetBlockCount() const = 0; - virtual void SetBlockSize(uint bytes) {} - virtual void SetDataOffset(int bytes) {} + virtual void SetBlockSize(u32 bytes) {} + virtual void SetDataOffset(u32 bytes) {} - uint GetBlockSize() const { return m_blocksize; } - - const std::string& GetFilename() const - { - return m_filename; - } + const std::string& GetFilename() const { return m_filename; } + u32 GetBlockSize() const { return m_blocksize; } }; -class FlatFileReader : public AsyncFileReader +class FlatFileReader final : public AsyncFileReader { - DeclareNoncopyableObject( FlatFileReader ); + DeclareNoncopyableObject(FlatFileReader); #ifdef _WIN32 HANDLE hOverlappedFile; @@ -86,65 +88,66 @@ class FlatFileReader : public AsyncFileReader public: FlatFileReader(bool shareWrite = false); - virtual ~FlatFileReader() override; + ~FlatFileReader() override; - virtual bool Open(std::string fileName) override; + bool Open(std::string filenae, Error* error) override; - virtual int ReadSync(void* pBuffer, uint sector, uint count) override; + int ReadSync(void* pBuffer, u32 sector, u32 count) override; - virtual void BeginRead(void* pBuffer, uint sector, uint count) override; - virtual int FinishRead(void) override; - virtual void CancelRead(void) override; + void BeginRead(void* pBuffer, u32 sector, u32 count) override; + int FinishRead() override; + void CancelRead() override; - virtual void Close(void) override; + void Close() override; - virtual uint GetBlockCount(void) const override; + u32 GetBlockCount() const override; - virtual void SetBlockSize(uint bytes) override { m_blocksize = bytes; } - virtual void SetDataOffset(int bytes) override { m_dataoffset = bytes; } + void SetBlockSize(u32 bytes) override { m_blocksize = bytes; } + void SetDataOffset(u32 bytes) override { m_dataoffset = bytes; } }; -class MultipartFileReader : public AsyncFileReader +class MultipartFileReader final : public AsyncFileReader { - DeclareNoncopyableObject( MultipartFileReader ); + DeclareNoncopyableObject(MultipartFileReader); static const int MaxParts = 8; - struct Part { - uint start; - uint end; // exclusive + struct Part + { + u32 start; + u32 end; // exclusive bool isReading; AsyncFileReader* reader; } m_parts[MaxParts]; - uint m_numparts; + u32 m_numparts; - uint GetFirstPart(uint lsn); + u32 GetFirstPart(u32 lsn); void FindParts(); public: MultipartFileReader(AsyncFileReader* firstPart); - virtual ~MultipartFileReader() override; + ~MultipartFileReader() override; - virtual bool Open(std::string fileName) override; + bool Open(std::string filename, Error* error) override; - virtual int ReadSync(void* pBuffer, uint sector, uint count) override; + int ReadSync(void* pBuffer, u32 sector, u32 count) override; - virtual void BeginRead(void* pBuffer, uint sector, uint count) override; - virtual int FinishRead(void) override; - virtual void CancelRead(void) override; + void BeginRead(void* pBuffer, u32 sector, u32 count) override; + int FinishRead() override; + void CancelRead() override; - virtual void Close(void) override; + void Close() override; - virtual uint GetBlockCount(void) const override; + u32 GetBlockCount() const override; - virtual void SetBlockSize(uint bytes) override; + void SetBlockSize(u32 bytes) override; static AsyncFileReader* DetectMultipart(AsyncFileReader* reader); }; class BlockdumpFileReader : public AsyncFileReader { - DeclareNoncopyableObject( BlockdumpFileReader ); + DeclareNoncopyableObject(BlockdumpFileReader); std::FILE* m_file; @@ -160,21 +163,21 @@ class BlockdumpFileReader : public AsyncFileReader public: BlockdumpFileReader(); - virtual ~BlockdumpFileReader() override; + ~BlockdumpFileReader() override; - virtual bool Open(std::string fileName) override; + bool Open(std::string filename, Error* error) override; - virtual int ReadSync(void* pBuffer, uint sector, uint count) override; + int ReadSync(void* pBuffer, u32 sector, u32 count) override; - virtual void BeginRead(void* pBuffer, uint sector, uint count) override; - virtual int FinishRead(void) override; - virtual void CancelRead(void) override; + void BeginRead(void* pBuffer, u32 sector, u32 count) override; + int FinishRead() override; + void CancelRead() override; - virtual void Close(void) override; + void Close() override; - virtual uint GetBlockCount(void) const override; + u32 GetBlockCount() const override; static bool DetectBlockdump(AsyncFileReader* reader); - int GetBlockOffset() { return m_blockofs; } + s32 GetBlockOffset() { return m_blockofs; } }; diff --git a/pcsx2/CDVD/BlockdumpFileReader.cpp b/pcsx2/CDVD/BlockdumpFileReader.cpp index 48e3e85fdc..4cce8ce9cb 100644 --- a/pcsx2/CDVD/BlockdumpFileReader.cpp +++ b/pcsx2/CDVD/BlockdumpFileReader.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2014 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -18,6 +18,7 @@ #include "IsoFileFormats.h" #include "common/Assertions.h" #include "common/FileSystem.h" +#include "common/Error.h" #include @@ -27,11 +28,11 @@ enum isoFlags ISOFLAGS_BLOCKDUMP_V3 = 0x0020 }; -static const uint BlockDumpHeaderSize = 16; +static constexpr u32 BlockDumpHeaderSize = 16; bool BlockdumpFileReader::DetectBlockdump(AsyncFileReader* reader) { - uint oldbs = reader->GetBlockSize(); + u32 oldbs = reader->GetBlockSize(); reader->SetBlockSize(1); @@ -45,7 +46,7 @@ bool BlockdumpFileReader::DetectBlockdump(AsyncFileReader* reader) return isbd; } -BlockdumpFileReader::BlockdumpFileReader(void) +BlockdumpFileReader::BlockdumpFileReader() : m_file(NULL) , m_blocks(0) , m_blockofs(0) @@ -54,19 +55,22 @@ BlockdumpFileReader::BlockdumpFileReader(void) { } -BlockdumpFileReader::~BlockdumpFileReader(void) +BlockdumpFileReader::~BlockdumpFileReader() { Close(); } -bool BlockdumpFileReader::Open(std::string fileName) +bool BlockdumpFileReader::Open(std::string filename, Error* error) { char signature[4]; - m_filename = std::move(fileName); - m_file = FileSystem::OpenCFile(m_filename.c_str(), "rb"); - if (!m_file || std::fread(signature, sizeof(signature), 1, m_file) != 1 || std::memcmp(signature, "BDV2", sizeof(signature)) != 0) + m_filename = std::move(filename); + if (!(m_file = FileSystem::OpenCFile(m_filename.c_str(), "rb", error))) + return false; + + if (std::fread(signature, sizeof(signature), 1, m_file) != 1 || std::memcmp(signature, "BDV2", sizeof(signature)) != 0) { + Error::SetString(error, "Block dump signature is invalid."); return false; } @@ -75,6 +79,7 @@ bool BlockdumpFileReader::Open(std::string fileName) || std::fread(&m_blocks, sizeof(m_blocks), 1, m_file) != 1 || std::fread(&m_blockofs, sizeof(m_blockofs), 1, m_file) != 1) { + Error::SetString(error, "Failed to read block dump information."); return false; } @@ -87,7 +92,10 @@ bool BlockdumpFileReader::Open(std::string fileName) m_dtable = std::make_unique(m_dtablesize); if (FileSystem::FSeek64(m_file, BlockDumpHeaderSize, SEEK_SET) != 0) + { + Error::SetString(error, "Failed to seek to block dump data."); return false; + } u32 bs = 1024 * 1024; u32 off = 0; @@ -112,7 +120,7 @@ bool BlockdumpFileReader::Open(std::string fileName) return true; } -int BlockdumpFileReader::ReadSync(void* pBuffer, uint lsn, uint count) +int BlockdumpFileReader::ReadSync(void* pBuffer, u32 lsn, u32 count) { u8* dst = (u8*)pBuffer; // Console.WriteLn("_isoReadBlockD %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs); @@ -159,17 +167,17 @@ int BlockdumpFileReader::ReadSync(void* pBuffer, uint lsn, uint count) return 0; } -void BlockdumpFileReader::BeginRead(void* pBuffer, uint sector, uint count) +void BlockdumpFileReader::BeginRead(void* pBuffer, u32 sector, u32 count) { m_lresult = ReadSync(pBuffer, sector, count); } -int BlockdumpFileReader::FinishRead(void) +int BlockdumpFileReader::FinishRead() { return m_lresult; } -void BlockdumpFileReader::CancelRead(void) +void BlockdumpFileReader::CancelRead() { } @@ -178,11 +186,11 @@ void BlockdumpFileReader::Close(void) if (m_file) { std::fclose(m_file); - m_file = NULL; + m_file = nullptr; } } -uint BlockdumpFileReader::GetBlockCount(void) const +u32 BlockdumpFileReader::GetBlockCount() const { return m_blocks; } diff --git a/pcsx2/CDVD/CDVDcommon.cpp b/pcsx2/CDVD/CDVDcommon.cpp index f345d12c2d..10688e5660 100644 --- a/pcsx2/CDVD/CDVDcommon.cpp +++ b/pcsx2/CDVD/CDVDcommon.cpp @@ -38,7 +38,7 @@ #define ENABLE_TIMESTAMPS -CDVD_API* CDVD = nullptr; +const CDVD_API* CDVD = nullptr; // ---------------------------------------------------------------------------- // diskTypeCached @@ -327,7 +327,7 @@ void CDVDsys_ClearFiles() void CDVDsys_ChangeSource(CDVD_SourceType type) { - if (CDVD != NULL) + if (CDVD) DoCDVDclose(); switch (m_CurrentSourceType = type) @@ -348,15 +348,14 @@ void CDVDsys_ChangeSource(CDVD_SourceType type) } } -bool DoCDVDopen() +bool DoCDVDopen(Error* error) { CheckNullCDVD(); CDVD->newDiskCB(cdvdNewDiskCB); auto CurrentSourceType = enum_cast(m_CurrentSourceType); - int ret = CDVD->open(!m_SourceFilename[CurrentSourceType].empty() ? m_SourceFilename[CurrentSourceType].c_str() : nullptr); - if (ret == -1) + if (!CDVD->open(m_SourceFilename[CurrentSourceType], error)) return false; // error! (handled by caller) int cdtype = DoCDVDdetectDiskType(); @@ -428,8 +427,7 @@ void DoCDVDclose() blockDumpFile.Close(); - if (CDVD->close != NULL) - CDVD->close(); + CDVD->close(); DoCDVDresetDiskTypeCache(); } @@ -530,75 +528,75 @@ void DoCDVDresetDiskTypeCache() -s32 CALLBACK NODISCopen(const char* pTitle) +static bool NODISCopen(std::string filename, Error* error) { - return 0; + return true; } -void CALLBACK NODISCclose() +static void NODISCclose() { } -s32 CALLBACK NODISCreadTrack(u32 lsn, int mode) +static s32 NODISCreadTrack(u32 lsn, int mode) { return -1; } -s32 CALLBACK NODISCgetBuffer(u8* buffer) +static s32 NODISCgetBuffer(u8* buffer) { return -1; } -s32 CALLBACK NODISCreadSubQ(u32 lsn, cdvdSubQ* subq) +static s32 NODISCreadSubQ(u32 lsn, cdvdSubQ* subq) { return -1; } -s32 CALLBACK NODISCgetTN(cdvdTN* Buffer) +static s32 NODISCgetTN(cdvdTN* Buffer) { return -1; } -s32 CALLBACK NODISCgetTD(u8 Track, cdvdTD* Buffer) +static s32 NODISCgetTD(u8 Track, cdvdTD* Buffer) { return -1; } -s32 CALLBACK NODISCgetTOC(void* toc) +static s32 NODISCgetTOC(void* toc) { return -1; } -s32 CALLBACK NODISCgetDiskType() +static s32 NODISCgetDiskType() { return CDVD_TYPE_NODISC; } -s32 CALLBACK NODISCgetTrayStatus() +static s32 NODISCgetTrayStatus() { return CDVD_TRAY_CLOSE; } -s32 CALLBACK NODISCdummyS32() +static s32 NODISCdummyS32() { return 0; } -void CALLBACK NODISCnewDiskCB(void (*/* callback */)()) +static void NODISCnewDiskCB(void (*/* callback */)()) { } -s32 CALLBACK NODISCreadSector(u8* tempbuffer, u32 lsn, int mode) +static s32 NODISCreadSector(u8* tempbuffer, u32 lsn, int mode) { return -1; } -s32 CALLBACK NODISCgetDualInfo(s32* dualType, u32* _layer1start) +static s32 NODISCgetDualInfo(s32* dualType, u32* _layer1start) { return -1; } -CDVD_API CDVDapi_NoDisc = +const CDVD_API CDVDapi_NoDisc = { NODISCclose, NODISCopen, diff --git a/pcsx2/CDVD/CDVDcommon.h b/pcsx2/CDVD/CDVDcommon.h index dc584db96a..88a16107b0 100644 --- a/pcsx2/CDVD/CDVDcommon.h +++ b/pcsx2/CDVD/CDVDcommon.h @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -16,19 +16,21 @@ #pragma once #include +class Error; + typedef struct _cdvdSubQ { - u8 ctrl : 4; // control and mode bits - u8 mode : 4; // control and mode bits - u8 trackNum; // current track number (1 to 99) + u8 ctrl : 4; // control and mode bits + u8 mode : 4; // control and mode bits + u8 trackNum; // current track number (1 to 99) u8 trackIndex; // current index within track (0 to 99) - u8 trackM; // current minute location on the disc (BCD encoded) - u8 trackS; // current sector location on the disc (BCD encoded) - u8 trackF; // current frame location on the disc (BCD encoded) - u8 pad; // unused - u8 discM; // current minute offset from first track (BCD encoded) - u8 discS; // current sector offset from first track (BCD encoded) - u8 discF; // current frame offset from first track (BCD encoded) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) } cdvdSubQ; typedef struct _cdvdTD @@ -44,9 +46,9 @@ typedef struct _cdvdTN } cdvdTN; // SpindleCtrl Masks -#define CDVD_SPINDLE_SPEED 0x7 // Speed ranges from 0-3 (1, 2, 3, 4x for DVD) and 0-5 (1, 2, 4, 12, 24x for CD) +#define CDVD_SPINDLE_SPEED 0x7 // Speed ranges from 0-3 (1, 2, 3, 4x for DVD) and 0-5 (1, 2, 4, 12, 24x for CD) #define CDVD_SPINDLE_NOMINAL 0x40 // Changes the speed to be constant (CLV) based on current speed -#define CDVD_SPINDLE_CAV 0x80 // CAV/CLV selector +#define CDVD_SPINDLE_CAV 0x80 // CAV/CLV selector // CDVDreadTrack mode values: #define CDVD_MODE_2352 0 // full 2352 bytes @@ -56,20 +58,20 @@ typedef struct _cdvdTN #define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq // CDVDgetDiskType returns: -#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc -#define CDVD_TYPE_DVDV 0xfe // DVD Video -#define CDVD_TYPE_CDDA 0xfd // Audio CD -#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD -#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) -#define CDVD_TYPE_PS2CD 0x12 // PS2 CD -#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) -#define CDVD_TYPE_PSCD 0x10 // PS CD -#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown #define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided #define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided -#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd -#define CDVD_TYPE_DETCT 0x01 // Detecting -#define CDVD_TYPE_NODISC 0x00 // No Disc +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc // CDVDgetTrayStatus returns: #define CDVD_TRAY_CLOSE 0x00 @@ -85,44 +87,42 @@ typedef struct _cdvdTN // CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) // CDVD -// NOTE: The read/write functions CANNOT use XMM/MMX regs -// If you want to use them, need to save and restore current ones -typedef s32(CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef bool (*_CDVDopen)(std::string filename, Error* error); // Initiates an asynchronous track read operation. // Returns -1 on error (invalid track) // Returns 0 on success. -typedef s32(CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef s32 (*_CDVDreadTrack)(u32 lsn, int mode); // Copies loaded data to the target buffer. // Returns -2 if the asynchronous read is still pending. // Returns -1 if the asyncronous read failed. // Returns 0 on success. -typedef s32(CALLBACK* _CDVDgetBuffer)(u8* buffer); +typedef s32 (*_CDVDgetBuffer)(u8* buffer); -typedef s32(CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); -typedef s32(CALLBACK* _CDVDgetTN)(cdvdTN* Buffer); -typedef s32(CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD* Buffer); -typedef s32(CALLBACK* _CDVDgetTOC)(void* toc); -typedef s32(CALLBACK* _CDVDgetDiskType)(); -typedef s32(CALLBACK* _CDVDgetTrayStatus)(); -typedef s32(CALLBACK* _CDVDctrlTrayOpen)(); -typedef s32(CALLBACK* _CDVDctrlTrayClose)(); -typedef s32(CALLBACK* _CDVDreadSector)(u8* buffer, u32 lsn, int mode); -typedef s32(CALLBACK* _CDVDgetDualInfo)(s32* dualType, u32* _layer1start); +typedef s32 (*_CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (*_CDVDgetTN)(cdvdTN* Buffer); +typedef s32 (*_CDVDgetTD)(u8 Track, cdvdTD* Buffer); +typedef s32 (*_CDVDgetTOC)(void* toc); +typedef s32 (*_CDVDgetDiskType)(); +typedef s32 (*_CDVDgetTrayStatus)(); +typedef s32 (*_CDVDctrlTrayOpen)(); +typedef s32 (*_CDVDctrlTrayClose)(); +typedef s32 (*_CDVDreadSector)(u8* buffer, u32 lsn, int mode); +typedef s32 (*_CDVDgetDualInfo)(s32* dualType, u32* _layer1start); -typedef void(CALLBACK* _CDVDnewDiskCB)(void (*callback)()); +typedef void (*_CDVDnewDiskCB)(void (*callback)()); enum class CDVD_SourceType : uint8_t { - Iso, // use built in ISO api - Disc, // use built in Disc api + Iso, // use built in ISO api + Disc, // use built in Disc api NoDisc, // use built in CDVDnull }; struct CDVD_API { - void(CALLBACK* close)(); + void (*close)(); // Don't need init or shutdown. iso/nodisc have no init/shutdown. @@ -148,11 +148,11 @@ struct CDVD_API // Multiple interface system for CDVD. // ---------------------------------------------------------------------------- -extern CDVD_API* CDVD; // currently active CDVD access mode api (either Iso, NoDisc, or Disc) +extern const CDVD_API* CDVD; // currently active CDVD access mode api (either Iso, NoDisc, or Disc) -extern CDVD_API CDVDapi_Iso; -extern CDVD_API CDVDapi_Disc; -extern CDVD_API CDVDapi_NoDisc; +extern const CDVD_API CDVDapi_Iso; +extern const CDVD_API CDVDapi_Disc; +extern const CDVD_API CDVDapi_NoDisc; extern void CDVDsys_ChangeSource(CDVD_SourceType type); extern void CDVDsys_SetFile(CDVD_SourceType srctype, std::string newfile); @@ -160,7 +160,7 @@ extern const std::string& CDVDsys_GetFile(CDVD_SourceType srctype); extern CDVD_SourceType CDVDsys_GetSourceType(); extern void CDVDsys_ClearFiles(); -extern bool DoCDVDopen(); +extern bool DoCDVDopen(Error* error); extern void DoCDVDclose(); extern s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode); extern s32 DoCDVDreadTrack(u32 lsn, int mode); diff --git a/pcsx2/CDVD/CDVDdiscReader.cpp b/pcsx2/CDVD/CDVDdiscReader.cpp index 6b58e2ac70..97ebba3afb 100644 --- a/pcsx2/CDVD/CDVDdiscReader.cpp +++ b/pcsx2/CDVD/CDVDdiscReader.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2020 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -17,6 +17,8 @@ #include "CDVDdiscReader.h" #include "CDVD/CDVD.h" +#include "common/Error.h" + #include #include #include @@ -41,19 +43,19 @@ int curTrayStatus; static u32 csector; int cmode; -int lastReadInNewDiskCB = 0; -u8 directReadSectorBuffer[2448]; +static int lastReadInNewDiskCB = 0; +static u8 directReadSectorBuffer[2448]; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // Utility Functions // -inline u8 dec_to_bcd(u8 dec) +static u8 dec_to_bcd(u8 dec) { return ((dec / 10) << 4) | (dec % 10); } -inline void lsn_to_msf(u8* minute, u8* second, u8* frame, u32 lsn) +static void lsn_to_msf(u8* minute, u8* second, u8* frame, u32 lsn) { *frame = dec_to_bcd(lsn % 75); lsn /= 75; @@ -130,7 +132,7 @@ extern u32 g_last_sector_block_lsn; /////////////////////////////////////////////////////////////////////////////// // keepAliveThread throws a read event regularly to prevent drive spin down // -void keepAliveThread() +static void keepAliveThread() { u8 throwaway[2352]; @@ -175,29 +177,33 @@ void StopKeepAliveThread() s_keepalive_thread.join(); } -s32 CALLBACK DISCopen(const char* pTitle) +static bool DISCopen(std::string filename, Error* error) { - std::string drive(pTitle); + std::string drive = filename; GetValidDrive(drive); if (drive.empty()) - return -1; + { + Error::SetString(error, fmt::format("Failed to get drive for {}", filename)); + return false; + } // open device file src = std::make_unique(std::move(drive)); - if (!src->Reopen()) + if (!src->Reopen(error)) { src.reset(); - return -1; + return false; } //setup threading manager cdvdStartThread(); StartKeepAliveThread(); - return cdvdRefreshData(); + cdvdRefreshData(); + return true; } -void CALLBACK DISCclose() +static void DISCclose() { StopKeepAliveThread(); cdvdStopThread(); @@ -205,7 +211,7 @@ void CALLBACK DISCclose() src.reset(); } -s32 CALLBACK DISCreadTrack(u32 lsn, int mode) +static s32 DISCreadTrack(u32 lsn, int mode) { csector = lsn; cmode = mode; @@ -223,7 +229,7 @@ s32 CALLBACK DISCreadTrack(u32 lsn, int mode) return 0; } -s32 CALLBACK DISCgetBuffer(u8* dest) +static s32 DISCgetBuffer(u8* dest) { // Do nothing for out of bounds disc sector reads. It prevents some games // from hanging (All-Star Baseball 2005, Hello Kitty: Roller Rescue, @@ -259,7 +265,7 @@ s32 CALLBACK DISCgetBuffer(u8* dest) return 0; } -s32 CALLBACK DISCreadSubQ(u32 lsn, cdvdSubQ* subq) +static s32 DISCreadSubQ(u32 lsn, cdvdSubQ* subq) { // the formatted subq command returns: control/adr, track, index, trk min, trk sec, trk frm, 0x00, abs min, abs sec, abs frm @@ -286,14 +292,14 @@ s32 CALLBACK DISCreadSubQ(u32 lsn, cdvdSubQ* subq) return 0; } -s32 CALLBACK DISCgetTN(cdvdTN* Buffer) +static s32 DISCgetTN(cdvdTN* Buffer) { Buffer->strack = strack; Buffer->etrack = etrack; return 0; } -s32 CALLBACK DISCgetTD(u8 Track, cdvdTD* Buffer) +static s32 DISCgetTD(u8 Track, cdvdTD* Buffer) { if (Track == 0) { @@ -315,7 +321,7 @@ s32 CALLBACK DISCgetTD(u8 Track, cdvdTD* Buffer) return 0; } -s32 CALLBACK DISCgetTOC(void* toc) +static s32 DISCgetTOC(void* toc) { u8* tocBuff = static_cast(toc); if (curDiskType == CDVD_TYPE_NODISC) @@ -478,39 +484,39 @@ s32 CALLBACK DISCgetTOC(void* toc) return 0; } -s32 CALLBACK DISCgetDiskType() +static s32 DISCgetDiskType() { return curDiskType; } -s32 CALLBACK DISCgetTrayStatus() +static s32 DISCgetTrayStatus() { return curTrayStatus; } -s32 CALLBACK DISCctrlTrayOpen() +static s32 DISCctrlTrayOpen() { curTrayStatus = CDVD_TRAY_OPEN; return 0; } -s32 CALLBACK DISCctrlTrayClose() +static s32 DISCctrlTrayClose() { curTrayStatus = CDVD_TRAY_CLOSE; return 0; } -void CALLBACK DISCnewDiskCB(void (*callback)()) +static void DISCnewDiskCB(void (*callback)()) { newDiscCB = callback; } -s32 CALLBACK DISCreadSector(u8* buffer, u32 lsn, int mode) +static s32 DISCreadSector(u8* buffer, u32 lsn, int mode) { return cdvdDirectReadSector(lsn, mode, buffer); } -s32 CALLBACK DISCgetDualInfo(s32* dualType, u32* _layer1start) +static s32 DISCgetDualInfo(s32* dualType, u32* _layer1start) { if (src == nullptr) return -1; @@ -532,7 +538,7 @@ s32 CALLBACK DISCgetDualInfo(s32* dualType, u32* _layer1start) return -1; } -CDVD_API CDVDapi_Disc = +const CDVD_API CDVDapi_Disc = { DISCclose, DISCopen, diff --git a/pcsx2/CDVD/CDVDdiscReader.h b/pcsx2/CDVD/CDVDdiscReader.h index 9a11158e9a..55e53b9cd1 100644 --- a/pcsx2/CDVD/CDVDdiscReader.h +++ b/pcsx2/CDVD/CDVDdiscReader.h @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2020 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -22,6 +22,8 @@ #include #include +class Error; + struct track { u32 start_lba; @@ -69,7 +71,7 @@ public: IOCtlSrc(std::string filename); ~IOCtlSrc(); - bool Reopen(); + bool Reopen(Error* error); u32 GetSectorCount() const; const std::vector& ReadTOC() const; @@ -96,6 +98,5 @@ void cdvdStopThread(); void cdvdRequestSector(u32 sector, s32 mode); u8* cdvdGetSector(u32 sector, s32 mode); s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer); -s32 cdvdGetMediaType(); -s32 cdvdRefreshData(); +void cdvdRefreshData(); void cdvdParseTOC(); diff --git a/pcsx2/CDVD/CDVDdiscThread.cpp b/pcsx2/CDVD/CDVDdiscThread.cpp index 03c298a57d..1dda7390e3 100644 --- a/pcsx2/CDVD/CDVDdiscThread.cpp +++ b/pcsx2/CDVD/CDVDdiscThread.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2020 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -50,10 +50,10 @@ static std::atomic cdvd_is_open; //bits: 12 would use 1<<12 entries, or 4096*16 sectors ~ 128MB #define CACHE_SIZE 12 -const u32 CacheSize = 1U << CACHE_SIZE; -SectorInfo Cache[CacheSize]; +static constexpr u32 CacheSize = 1U << CACHE_SIZE; +static SectorInfo Cache[CacheSize]; -u32 cdvdSectorHash(u32 lsn) +static u32 cdvdSectorHash(u32 lsn) { u32 t = 0; @@ -70,7 +70,7 @@ u32 cdvdSectorHash(u32 lsn) return t & m; } -void cdvdCacheUpdate(u32 lsn, u8* data) +static void cdvdCacheUpdate(u32 lsn, u8* data) { std::lock_guard guard(s_cache_lock); u32 entry = cdvdSectorHash(lsn); @@ -79,7 +79,7 @@ void cdvdCacheUpdate(u32 lsn, u8* data) Cache[entry].lsn = lsn; } -bool cdvdCacheCheck(u32 lsn) +static bool cdvdCacheCheck(u32 lsn) { std::lock_guard guard(s_cache_lock); u32 entry = cdvdSectorHash(lsn); @@ -87,7 +87,7 @@ bool cdvdCacheCheck(u32 lsn) return Cache[entry].lsn == lsn; } -bool cdvdCacheFetch(u32 lsn, u8* data) +static bool cdvdCacheFetch(u32 lsn, u8* data) { std::lock_guard guard(s_cache_lock); u32 entry = cdvdSectorHash(lsn); @@ -101,7 +101,7 @@ bool cdvdCacheFetch(u32 lsn, u8* data) return false; } -void cdvdCacheReset() +static void cdvdCacheReset() { std::lock_guard guard(s_cache_lock); for (u32 i = 0; i < CacheSize; i++) @@ -110,7 +110,7 @@ void cdvdCacheReset() } } -bool cdvdReadBlockOfSectors(u32 sector, u8* data) +static bool cdvdReadBlockOfSectors(u32 sector, u8* data) { u32 count = std::min(sectors_per_read, src->GetSectorCount() - sector); const s32 media = src->GetMediaType(); @@ -133,14 +133,14 @@ bool cdvdReadBlockOfSectors(u32 sector, u8* data) return false; } -void cdvdCallNewDiscCB() +static void cdvdCallNewDiscCB() { weAreInNewDiskCB = true; newDiscCB(); weAreInNewDiskCB = false; } -bool cdvdUpdateDiscStatus() +static bool cdvdUpdateDiscStatus() { bool ready = src->DiscReady(); @@ -175,7 +175,7 @@ bool cdvdUpdateDiscStatus() return !ready; } -void cdvdThread() +static void cdvdThread() { u8 buffer[2352 * sectors_per_read]; u32 prefetches_left = 0; @@ -379,12 +379,12 @@ s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer) } } -s32 cdvdGetMediaType() +static s32 cdvdGetMediaType() { return src->GetMediaType(); } -s32 cdvdRefreshData() +void cdvdRefreshData() { const char* diskTypeName = "Unknown"; @@ -428,6 +428,4 @@ s32 cdvdRefreshData() printf(" * CDVD: Disk Type: %s\n", diskTypeName); cdvdCacheReset(); - - return 0; } diff --git a/pcsx2/CDVD/CDVDisoReader.cpp b/pcsx2/CDVD/CDVDisoReader.cpp index 364a8a8e49..f9e5c6afe5 100644 --- a/pcsx2/CDVD/CDVDisoReader.cpp +++ b/pcsx2/CDVD/CDVDisoReader.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -13,19 +13,13 @@ * If not, see . */ - -/* - * Original code from libcdvd by Hiryu & Sjeep (C) 2002 - * Modified by Florin for PCSX2 emu - * Fixed CdRead by linuzappz - */ - #include "PrecompiledHeader.h" #include "IsoFileFormats.h" #include "AsyncFileReader.h" #include "CDVD/CDVD.h" #include "common/Assertions.h" +#include "common/Error.h" #include #include @@ -37,23 +31,23 @@ static int pmode, cdtype; static s32 layer1start = -1; static bool layer1searched = false; -void CALLBACK ISOclose() +static void ISOclose() { iso.Close(); } -s32 CALLBACK ISOopen(const char* pTitle) +static bool ISOopen(std::string filename, Error* error) { ISOclose(); // just in case - if ((pTitle == NULL) || (pTitle[0] == 0)) + if (filename.empty()) { - Console.Error("CDVDiso Error: No filename specified."); - return -1; + Error::SetString(error, "No filename specified."); + return false; } - if (!iso.Open(pTitle)) - return -1; + if (!iso.Open(std::move(filename), error, false)) + return false; switch (iso.GetType()) { @@ -71,10 +65,10 @@ s32 CALLBACK ISOopen(const char* pTitle) layer1start = -1; layer1searched = false; - return 0; + return true; } -s32 CALLBACK ISOreadSubQ(u32 lsn, cdvdSubQ* subq) +static s32 ISOreadSubQ(u32 lsn, cdvdSubQ* subq) { // fake it u8 min, sec, frm; @@ -98,7 +92,7 @@ s32 CALLBACK ISOreadSubQ(u32 lsn, cdvdSubQ* subq) return 0; } -s32 CALLBACK ISOgetTN(cdvdTN* Buffer) +static s32 ISOgetTN(cdvdTN* Buffer) { Buffer->strack = 1; Buffer->etrack = 1; @@ -106,7 +100,7 @@ s32 CALLBACK ISOgetTN(cdvdTN* Buffer) return 0; } -s32 CALLBACK ISOgetTD(u8 Track, cdvdTD* Buffer) +static s32 ISOgetTD(u8 Track, cdvdTD* Buffer) { if (Track == 0) { @@ -170,7 +164,7 @@ static void FindLayer1Start() } // Should return 0 if no error occurred, or -1 if layer detection FAILED. -s32 CALLBACK ISOgetDualInfo(s32* dualType, u32* _layer1start) +static s32 ISOgetDualInfo(s32* dualType, u32* _layer1start) { FindLayer1Start(); @@ -187,12 +181,12 @@ s32 CALLBACK ISOgetDualInfo(s32* dualType, u32* _layer1start) return 0; } -s32 CALLBACK ISOgetDiskType() +static s32 ISOgetDiskType() { return cdtype; } -s32 CALLBACK ISOgetTOC(void* toc) +static s32 ISOgetTOC(void* toc) { u8 type = ISOgetDiskType(); u8* tocBuff = (u8*)toc; @@ -326,7 +320,7 @@ s32 CALLBACK ISOgetTOC(void* toc) return 0; } -s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode) +static s32 ISOreadSector(u8* tempbuffer, u32 lsn, int mode) { static u8 cdbuffer[CD_FRAMESIZE_RAW] = {0}; @@ -377,7 +371,7 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode) return 0; } -s32 CALLBACK ISOreadTrack(u32 lsn, int mode) +static s32 ISOreadTrack(u32 lsn, int mode) { int _lsn = lsn; @@ -391,41 +385,41 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode) return 0; } -s32 CALLBACK ISOgetBuffer(u8* buffer) +static s32 ISOgetBuffer(u8* buffer) { return iso.FinishRead3(buffer, pmode); } -//u8* CALLBACK ISOgetBuffer() +//static u8* ISOgetBuffer() //{ // iso.FinishRead(); // return pbuffer; //} -s32 CALLBACK ISOgetTrayStatus() +static s32 ISOgetTrayStatus() { return CDVD_TRAY_CLOSE; } -s32 CALLBACK ISOctrlTrayOpen() +static s32 ISOctrlTrayOpen() { return 0; } -s32 CALLBACK ISOctrlTrayClose() +static s32 ISOctrlTrayClose() { return 0; } -s32 CALLBACK ISOdummyS32() +static s32 ISOdummyS32() { return 0; } -void CALLBACK ISOnewDiskCB(void (*/* callback */)()) +static void ISOnewDiskCB(void (* /* callback */)()) { } -CDVD_API CDVDapi_Iso = +const CDVD_API CDVDapi_Iso = { ISOclose, @@ -440,7 +434,6 @@ CDVD_API CDVDapi_Iso = ISOdummyS32, // trayStatus ISOdummyS32, // trayOpen ISOdummyS32, // trayClose - ISOnewDiskCB, ISOreadSector, diff --git a/pcsx2/CDVD/ChdFileReader.cpp b/pcsx2/CDVD/ChdFileReader.cpp index 257259b36a..f9be167664 100644 --- a/pcsx2/CDVD/ChdFileReader.cpp +++ b/pcsx2/CDVD/ChdFileReader.cpp @@ -176,27 +176,19 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt return chd; } -bool ChdFileReader::Open2(std::string fileName) +bool ChdFileReader::Open2(std::string filename, Error* error) { Close2(); - m_filename = std::move(fileName); + m_filename = std::move(filename); - auto fp = FileSystem::OpenManagedSharedCFile(m_filename.c_str(), "rb", FileSystem::FileShareMode::DenyWrite); + auto fp = FileSystem::OpenManagedSharedCFile(m_filename.c_str(), "rb", FileSystem::FileShareMode::DenyWrite, error); if (!fp) - { - Console.Error(fmt::format("Failed to open CHD '{}': errno {}", m_filename, errno)); return false; - } - // TODO: Propagate error back to caller. - Error error; - ChdFile = OpenCHD(m_filename, std::move(fp), &error, 0); + ChdFile = OpenCHD(m_filename, std::move(fp), error, 0); if (!ChdFile) - { - Console.Error(fmt::format("Failed to open CHD '{}': {}", m_filename, error.GetDescription())); return false; - } const chd_header* chd_header = chd_get_header(ChdFile); hunk_size = chd_header->hunkbytes; diff --git a/pcsx2/CDVD/ChdFileReader.h b/pcsx2/CDVD/ChdFileReader.h index 89ed7bc6b5..cc28001e7e 100644 --- a/pcsx2/CDVD/ChdFileReader.h +++ b/pcsx2/CDVD/ChdFileReader.h @@ -19,17 +19,17 @@ typedef struct _chd_file chd_file; -class ChdFileReader : public ThreadedFileReader +class ChdFileReader final : public ThreadedFileReader { DeclareNoncopyableObject(ChdFileReader); public: ChdFileReader(); - virtual ~ChdFileReader() override; + ~ChdFileReader() override; static bool CanHandle(const std::string& fileName, const std::string& displayName); - bool Open2(std::string fileName) override; + bool Open2(std::string filename, Error* error) override; Chunk ChunkForOffset(u64 offset) override; int ReadChunk(void* dst, s64 blockID) override; diff --git a/pcsx2/CDVD/CsoFileReader.cpp b/pcsx2/CDVD/CsoFileReader.cpp index dbd66d220b..cb6e7c0b96 100644 --- a/pcsx2/CDVD/CsoFileReader.cpp +++ b/pcsx2/CDVD/CsoFileReader.cpp @@ -1,29 +1,31 @@ /* PCSX2 - PS2 Emulator for PCs -* Copyright (C) 2002-2023 PCSX2 Dev Team -* -* PCSX2 is free software: you can redistribute it and/or modify it under the terms -* of the GNU Lesser General Public License as published by the Free Software Found- -* ation, either version 3 of the License, or (at your option) any later version. -* -* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -* PURPOSE. See the GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License along with PCSX2. -* If not, see . -*/ + * Copyright (C) 2002-2023 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ #include "PrecompiledHeader.h" #include "AsyncFileReader.h" #include "CsoFileReader.h" -#include "common/Pcsx2Types.h" #include "common/FileSystem.h" +#include "common/Error.h" #include "common/StringUtil.h" #include +static constexpr u32 CSO_CHUNKCACHE_SIZE_MB = 200; + // Implementation of CSO compressed ISO reading, based on: // https://github.com/unknownbrackets/maxcso/blob/master/README_CSO.md struct CsoHeader @@ -39,6 +41,16 @@ struct CsoHeader static const u32 CSO_READ_BUFFER_SIZE = 256 * 1024; +CsoFileReader::CsoFileReader() +{ + m_blocksize = 2048; +} + +CsoFileReader::~CsoFileReader() +{ + Close(); +} + bool CsoFileReader::CanHandle(const std::string& fileName, const std::string& displayName) { bool supported = false; @@ -50,7 +62,7 @@ bool CsoFileReader::CanHandle(const std::string& fileName, const std::string& di { if (fread(&hdr, 1, sizeof(hdr), fp) == sizeof(hdr)) { - supported = ValidateHeader(hdr); + supported = ValidateHeader(hdr, nullptr); } fclose(fp); } @@ -58,26 +70,27 @@ bool CsoFileReader::CanHandle(const std::string& fileName, const std::string& di return supported; } -bool CsoFileReader::ValidateHeader(const CsoHeader& hdr) +bool CsoFileReader::ValidateHeader(const CsoHeader& hdr, Error* error) { if (hdr.magic[0] != 'C' || hdr.magic[1] != 'I' || hdr.magic[2] != 'S' || hdr.magic[3] != 'O') { // Invalid magic, definitely a bad file. + Error::SetString(error, "File is not a CHD."); return false; } if (hdr.ver > 1) { - Console.Error("Only CSOv1 files are supported."); + Error::SetString(error, "Only CSOv1 files are supported."); return false; } if ((hdr.frame_size & (hdr.frame_size - 1)) != 0) { - Console.Error("CSO frame size must be a power of two."); + Error::SetString(error, "CSO frame size must be a power of two."); return false; } if (hdr.frame_size < 2048) { - Console.Error("CSO frame size must be at least one sector."); + Error::SetString(error, "CSO frame size must be at least one sector."); return false; } @@ -85,14 +98,14 @@ bool CsoFileReader::ValidateHeader(const CsoHeader& hdr) return true; } -bool CsoFileReader::Open2(std::string fileName) +bool CsoFileReader::Open2(std::string filename, Error* error) { Close2(); - m_filename = std::move(fileName); - m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb"); + m_filename = std::move(filename); + m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb", error); bool success = false; - if (m_src && ReadFileHeader() && InitializeBuffers()) + if (m_src && ReadFileHeader(error) && InitializeBuffers(error)) { success = true; } @@ -105,21 +118,18 @@ bool CsoFileReader::Open2(std::string fileName) return true; } -bool CsoFileReader::ReadFileHeader() +bool CsoFileReader::ReadFileHeader(Error* error) { - CsoHeader hdr = {}; + CsoHeader hdr; if (FileSystem::FSeek64(m_src, m_dataoffset, SEEK_SET) != 0 || std::fread(&hdr, 1, sizeof(hdr), m_src) != sizeof(hdr)) { - Console.Error("Failed to read CSO file header."); + Error::SetString(error, "Failed to read CSO file header."); return false; } - if (!ValidateHeader(hdr)) - { - Console.Error("CSO has invalid header."); + if (!ValidateHeader(hdr, error)) return false; - } m_frameSize = hdr.frame_size; // Determine the translation from bytes to frame. @@ -136,7 +146,7 @@ bool CsoFileReader::ReadFileHeader() return true; } -bool CsoFileReader::InitializeBuffers() +bool CsoFileReader::InitializeBuffers(Error* error) { // Round up, since part of a frame requires a full frame. u32 numFrames = (u32)((m_totalSize + m_frameSize - 1) / m_frameSize); @@ -144,28 +154,28 @@ bool CsoFileReader::InitializeBuffers() // We might read a bit of alignment too, so be prepared. if (m_frameSize + (1 << m_indexShift) < CSO_READ_BUFFER_SIZE) { - m_readBuffer = new u8[CSO_READ_BUFFER_SIZE]; + m_readBuffer = std::make_unique(CSO_READ_BUFFER_SIZE); } else { - m_readBuffer = new u8[m_frameSize + (1 << m_indexShift)]; + m_readBuffer = std::make_unique(m_frameSize + (1 << m_indexShift)); } const u32 indexSize = numFrames + 1; - m_index = new u32[indexSize]; - if (fread(m_index, sizeof(u32), indexSize, m_src) != indexSize) + m_index = std::make_unique(indexSize); + if (fread(m_index.get(), sizeof(u32), indexSize, m_src) != indexSize) { - Console.Error("Unable to read index data from CSO."); + Error::SetString(error, "Unable to read index data from CSO."); return false; } - m_z_stream = new z_stream; + m_z_stream = std::make_unique(); m_z_stream->zalloc = Z_NULL; m_z_stream->zfree = Z_NULL; m_z_stream->opaque = Z_NULL; - if (inflateInit2(m_z_stream, -15) != Z_OK) + if (inflateInit2(m_z_stream.get(), -15) != Z_OK) { - Console.Error("Unable to initialize zlib for CSO decompression."); + Error::SetString(error, "Unable to initialize zlib for CSO decompression."); return false; } @@ -179,24 +189,21 @@ void CsoFileReader::Close2() if (m_src) { fclose(m_src); - m_src = NULL; + m_src = nullptr; } if (m_z_stream) { - inflateEnd(m_z_stream); - m_z_stream = NULL; + inflateEnd(m_z_stream.get()); + m_z_stream.reset(); } - if (m_readBuffer) - { - delete[] m_readBuffer; - m_readBuffer = NULL; - } - if (m_index) - { - delete[] m_index; - m_index = NULL; - } + m_readBuffer.reset(); + m_index.reset(); +} + +u32 CsoFileReader::GetBlockCount() const +{ + return static_cast((m_totalSize - m_dataoffset) / m_blocksize); } ThreadedFileReader::Chunk CsoFileReader::ChunkForOffset(u64 offset) @@ -215,7 +222,7 @@ ThreadedFileReader::Chunk CsoFileReader::ChunkForOffset(u64 offset) return chunk; } -int CsoFileReader::ReadChunk(void *dst, s64 chunkID) +int CsoFileReader::ReadChunk(void* dst, s64 chunkID) { if (chunkID < 0) return -1; @@ -250,19 +257,19 @@ int CsoFileReader::ReadChunk(void *dst, s64 chunkID) } // This might be less bytes than frameRawSize in case of padding on the last frame. // This is because the index positions must be aligned. - const u32 readRawBytes = fread(m_readBuffer, 1, frameRawSize, m_src); + const u32 readRawBytes = fread(m_readBuffer.get(), 1, frameRawSize, m_src); - m_z_stream->next_in = m_readBuffer; + m_z_stream->next_in = m_readBuffer.get(); m_z_stream->avail_in = readRawBytes; m_z_stream->next_out = static_cast(dst); m_z_stream->avail_out = m_frameSize; - int status = inflate(m_z_stream, Z_FINISH); + int status = inflate(m_z_stream.get(), Z_FINISH); bool success = status == Z_STREAM_END && m_z_stream->total_out == m_frameSize; if (!success) Console.Error("Unable to decompress CSO frame using zlib."); - inflateReset(m_z_stream); + inflateReset(m_z_stream.get()); return success ? m_frameSize : 0; } diff --git a/pcsx2/CDVD/CsoFileReader.h b/pcsx2/CDVD/CsoFileReader.h index 239a1a21e3..297dedb02e 100644 --- a/pcsx2/CDVD/CsoFileReader.h +++ b/pcsx2/CDVD/CsoFileReader.h @@ -1,17 +1,17 @@ /* PCSX2 - PS2 Emulator for PCs -* Copyright (C) 2002-2014 PCSX2 Dev Team -* -* PCSX2 is free software: you can redistribute it and/or modify it under the terms -* of the GNU Lesser General Public License as published by the Free Software Found- -* ation, either version 3 of the License, or (at your option) any later version. -* -* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -* PURPOSE. See the GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License along with PCSX2. -* If not, see . -*/ + * Copyright (C) 2002-2023 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ #pragma once @@ -31,56 +31,40 @@ struct CsoHeader; typedef struct z_stream_s z_stream; -static const uint CSO_CHUNKCACHE_SIZE_MB = 200; - -class CsoFileReader : public ThreadedFileReader +class CsoFileReader final : public ThreadedFileReader { DeclareNoncopyableObject(CsoFileReader); public: - CsoFileReader(void) - : m_frameSize(0) - , m_frameShift(0) - , m_indexShift(0) - , m_readBuffer(0) - , m_index(0) - , m_totalSize(0) - , m_src(0) - , m_z_stream(0) - { - m_blocksize = 2048; - }; - - ~CsoFileReader(void) { Close(); }; + CsoFileReader(); + ~CsoFileReader() override; static bool CanHandle(const std::string& fileName, const std::string& displayName); - bool Open2(std::string fileName) override; + bool Open2(std::string filename, Error* error) override; Chunk ChunkForOffset(u64 offset) override; - int ReadChunk(void *dst, s64 chunkID) override; + int ReadChunk(void* dst, s64 chunkID) override; - void Close2(void) override; + void Close2() override; - uint GetBlockCount(void) const override - { - return (m_totalSize - m_dataoffset) / m_blocksize; - }; + u32 GetBlockCount() const override; private: - static bool ValidateHeader(const CsoHeader& hdr); - bool ReadFileHeader(); - bool InitializeBuffers(); + static bool ValidateHeader(const CsoHeader& hdr, Error* error); + bool ReadFileHeader(Error* error); + bool InitializeBuffers(Error* error); int ReadFromFrame(u8* dest, u64 pos, int maxBytes); bool DecompressFrame(Bytef* dst, u32 frame, u32 readBufferSize); bool DecompressFrame(u32 frame, u32 readBufferSize); - u32 m_frameSize; - u8 m_frameShift; - u8 m_indexShift; - u8* m_readBuffer;; - u32* m_index; - u64 m_totalSize; + u32 m_frameSize = 0; + u8 m_frameShift = 0; + u8 m_indexShift = 0; + std::unique_ptr m_readBuffer; + + std::unique_ptr m_index; + u64 m_totalSize = 0; // The actual source cso file handle. - FILE* m_src; - z_stream* m_z_stream; + std::FILE* m_src = nullptr; + std::unique_ptr m_z_stream; }; diff --git a/pcsx2/CDVD/Darwin/IOCtlSrc.cpp b/pcsx2/CDVD/Darwin/IOCtlSrc.cpp index d8ef61dd27..d3ae83a4b4 100644 --- a/pcsx2/CDVD/Darwin/IOCtlSrc.cpp +++ b/pcsx2/CDVD/Darwin/IOCtlSrc.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2022 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -17,6 +17,8 @@ #include "CDVD/CDVDdiscReader.h" #include "CDVD/CDVD.h" +#include "common/Error.h" + #ifdef __APPLE__ #include #include @@ -43,7 +45,7 @@ IOCtlSrc::~IOCtlSrc() } } -bool IOCtlSrc::Reopen() +bool IOCtlSrc::Reopen(Error* error) { if (m_device != -1) close(m_device); @@ -52,7 +54,10 @@ bool IOCtlSrc::Reopen() // drive is empty. Probably does other things too. m_device = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK); if (m_device == -1) + { + Error::SetErrno(error, errno); return false; + } // DVD detection MUST be first on Linux - The TOC ioctls work for both // CDs and DVDs. @@ -256,7 +261,7 @@ bool IOCtlSrc::DiscReady() if (!m_sectors) { - Reopen(); + Reopen(nullptr); } return !!m_sectors; diff --git a/pcsx2/CDVD/GzippedFileReader.cpp b/pcsx2/CDVD/GzippedFileReader.cpp index 29b62ff5e2..b0dfa56a86 100644 --- a/pcsx2/CDVD/GzippedFileReader.cpp +++ b/pcsx2/CDVD/GzippedFileReader.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs -* Copyright (C) 2002-2014 PCSX2 Dev Team +* Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -22,12 +22,12 @@ #include "CDVD/zlib_indexed.h" #include "common/FileSystem.h" +#include "common/Error.h" #include "common/Path.h" #include "common/StringUtil.h" +#include "common/Timer.h" -#include - -#define CLAMP(val, minval, maxval) (std::min(maxval, std::max(minval, val))) +#include "fmt/format.h" #define GZIP_ID "PCSX2.index.gzip.v1|" #define GZIP_ID_LEN (sizeof(GZIP_ID) - 1) /* sizeof includes the \0 terminator */ @@ -39,40 +39,43 @@ static Access* ReadIndexFromFile(const char* filename) { auto fp = FileSystem::OpenManagedCFile(filename, "rb"); + if (!fp) + return nullptr; + s64 size; - if (!fp || (size = FileSystem::FSize64(fp.get())) <= 0) + if ((size = FileSystem::FSize64(fp.get())) <= 0) { - Console.Error("Error: Can't open index file: '%s'", filename); - return 0; + Console.Error(fmt::format("Invalid gzip index size: {}", size)); + return nullptr; } char fileId[GZIP_ID_LEN + 1] = {0}; if (std::fread(fileId, GZIP_ID_LEN, 1, fp.get()) != 1 || std::memcmp(fileId, GZIP_ID, 4) != 0) { - Console.Error("Error: Incompatible gzip index, please delete it manually: '%s'", filename); - return 0; + Console.Error(fmt::format("Incompatible gzip index, please delete it manually: '{}'", filename)); + return nullptr; } - Access* const index = (Access*)malloc(sizeof(Access)); + Access* const index = static_cast(std::malloc(sizeof(Access))); const s64 datasize = size - GZIP_ID_LEN - sizeof(Access); if (std::fread(index, sizeof(Access), 1, fp.get()) != 1 || datasize != static_cast(index->have) * static_cast(sizeof(Point))) { - Console.Error("Error: Unexpected size of gzip index, please delete it manually: '%s'.", filename); - free(index); + Console.Error(fmt::format("Unexpected size of gzip index, please delete it manually: '{}'.", filename)); + std::free(index); return 0; } - char* buffer = (char*)malloc(datasize); + char* buffer = static_cast(std::malloc(datasize)); if (std::fread(buffer, datasize, 1, fp.get()) != 1) { - Console.Error("Error: failed read of gzip index, please delete it manually: '%s'.", filename); - free(buffer); - free(index); + Console.Error(fmt::format("Failed read of gzip index, please delete it manually: '{}'.", filename)); + std::free(buffer); + std::free(index); return 0; } - index->list = (Point*)buffer; // adjust list pointer + index->list = reinterpret_cast(buffer); // adjust list pointer return index; } @@ -120,20 +123,20 @@ static const char* INDEX_TEMPLATE_KEY = "$(f)"; // No checks are performed if the result file name can be created. // If this proves useful, we can move it into Path:: . Right now there's no need. static std::string ApplyTemplate(const std::string& name, const std::string& base, - const std::string& fileTemplate, const std::string& filename, - bool canEndWithKey) + const std::string& fileTemplate, const std::string& filename, + bool canEndWithKey, Error* error) { // both sides std::string trimmedTemplate(StringUtil::StripWhitespace(fileTemplate)); std::string::size_type first = trimmedTemplate.find(INDEX_TEMPLATE_KEY); - if (first == std::string::npos // not found + if (first == std::string::npos // not found || first != trimmedTemplate.rfind(INDEX_TEMPLATE_KEY) // more than one instance || (!canEndWithKey && first == trimmedTemplate.length() - std::strlen(INDEX_TEMPLATE_KEY))) { - Console.Error("Invalid %s template '%s'.\n" + Error::SetString(error, fmt::format("Invalid {} template '{}'.\n" "Template must contain exactly one '%s' and must not end with it. Aborting.", - name.c_str(), trimmedTemplate.c_str(), INDEX_TEMPLATE_KEY); + name, trimmedTemplate, INDEX_TEMPLATE_KEY)); return {}; } @@ -148,23 +151,23 @@ static std::string ApplyTemplate(const std::string& name, const std::string& bas return trimmedTemplate; } -static std::string iso2indexname(const std::string& isoname) +static std::string iso2indexname(const std::string& isoname, Error* error) { const std::string& appRoot = EmuFolders::DataRoot; - return ApplyTemplate("gzip index", appRoot, Host::GetBaseStringSettingValue("EmuCore", "GzipIsoIndexTemplate", "$(f).pindex.tmp"), isoname, false); + return ApplyTemplate("gzip index", appRoot, Host::GetBaseStringSettingValue("EmuCore", "GzipIsoIndexTemplate", "$(f).pindex.tmp"), isoname, false, error); } - -GzippedFileReader::GzippedFileReader(void) - : mBytesRead(0) - , m_pIndex(0) - , m_zstates(0) - , m_src(0) - , m_cache(GZFILE_CACHE_SIZE_MB) +GzippedFileReader::GzippedFileReader() + : m_cache(GZFILE_CACHE_SIZE_MB) { m_blocksize = 2048; AsyncPrefetchReset(); -}; +} + +GzippedFileReader::~GzippedFileReader() +{ + Close(); +} void GzippedFileReader::InitZstates() { @@ -268,15 +271,18 @@ bool GzippedFileReader::CanHandle(const std::string& fileName, const std::string return StringUtil::EndsWith(fileName, ".gz"); } -bool GzippedFileReader::OkIndex() +bool GzippedFileReader::OkIndex(Error* error) { if (m_pIndex) return true; // Try to read index from disk - const std::string indexfile(iso2indexname(m_filename)); + const std::string indexfile(iso2indexname(m_filename, error)); if (indexfile.empty()) - return false; // iso2indexname(...) will print errors if it can't apply the template + { + // iso2indexname(...) will set errors if it can't apply the template + return false; + } if (FileSystem::FileExists(indexfile.c_str()) && (m_pIndex = ReadIndexFromFile(indexfile.c_str()))) { @@ -284,7 +290,7 @@ bool GzippedFileReader::OkIndex() if (m_pIndex->span != GZFILE_SPAN_DEFAULT) { Console.Warning("Note: This index has %1.1f MB intervals, while the current default for new indexes is %1.1f MB.", - (float)m_pIndex->span / 1024 / 1024, (float)GZFILE_SPAN_DEFAULT / 1024 / 1024); + (float)m_pIndex->span / 1024 / 1024, (float)GZFILE_SPAN_DEFAULT / 1024 / 1024); Console.Warning("It will work fine, but if you want to generate a new index with default intervals, delete this index file."); Console.Warning("(smaller intervals mean bigger index file and quicker but more frequent decompressions)"); } @@ -308,7 +314,7 @@ bool GzippedFileReader::OkIndex() } else { - Console.Error("ERROR (%d): Index could not be generated for file '%s'", len, m_filename.c_str()); + Error::SetString(error, fmt::format("ERROR ({}): Index could not be generated for file '{}'", len, m_filename)); free_index(index); InitZstates(); return false; @@ -318,15 +324,15 @@ bool GzippedFileReader::OkIndex() return true; } -bool GzippedFileReader::Open(std::string fileName) +bool GzippedFileReader::Open(std::string filename, Error* error) { Close(); - m_filename = std::move(fileName); - if (!(m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb")) || !OkIndex()) + m_filename = std::move(filename); + if (!(m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb", error)) || !OkIndex(error)) { Close(); return false; - }; + } AsyncPrefetchOpen(); return true; @@ -336,18 +342,18 @@ void GzippedFileReader::BeginRead(void* pBuffer, uint sector, uint count) { // No a-sync support yet, implement as sync mBytesRead = ReadSync(pBuffer, sector, count); - return; -}; +} -int GzippedFileReader::FinishRead(void) +int GzippedFileReader::FinishRead() { int res = mBytesRead; mBytesRead = -1; return res; -}; +} -#define PTT clock_t -#define NOW() (clock() / (CLOCKS_PER_SEC / 1000)) +void GzippedFileReader::CancelRead() +{ +} int GzippedFileReader::ReadSync(void* pBuffer, uint sector, uint count) { @@ -378,7 +384,7 @@ s64 GzippedFileReader::GetOptimalExtractionStart(s64 offset) int GzippedFileReader::_ReadSync(void* pBuffer, s64 offset, uint bytesToRead) { - if (!OkIndex()) + if (!OkIndex(nullptr)) return -1; // Without all the caching, chunking and states, this would be enough: @@ -407,7 +413,7 @@ int GzippedFileReader::_ReadSync(void* pBuffer, s64 offset, uint bytesToRead) // Not available from cache. Decompress from optimal starting // point in GZFILE_READ_CHUNK_SIZE chunks and cache each chunk. - PTT s = NOW(); + Common::Timer start_time; s64 extractOffset = GetOptimalExtractionStart(offset); // guaranteed in GZFILE_READ_CHUNK_SIZE boundaries int size = offset + maxInChunk - extractOffset; unsigned char* extracted = (unsigned char*)malloc(size); @@ -446,7 +452,7 @@ int GzippedFileReader::_ReadSync(void* pBuffer, s64 offset, uint bytesToRead) { // split into cacheable chunks for (int i = 0; i < size; i += GZFILE_READ_CHUNK_SIZE) { - int available = CLAMP(res - i, 0, GZFILE_READ_CHUNK_SIZE); + int available = std::clamp(res - i, 0, GZFILE_READ_CHUNK_SIZE); void* chunk = available ? malloc(available) : 0; if (available) memcpy(chunk, extracted + i, available); @@ -455,13 +461,14 @@ int GzippedFileReader::_ReadSync(void* pBuffer, s64 offset, uint bytesToRead) free(extracted); } - int duration = NOW() - s; - if (duration > 10) + if (const double duration = start_time.GetTimeMilliseconds(); duration > 10) + { Console.WriteLn(Color_Gray, "gunzip: chunk #%5d-%2d : %1.2f MB - %d ms", - (int)(offset / 4 / 1024 / 1024), - (int)(offset % (4 * 1024 * 1024) / GZFILE_READ_CHUNK_SIZE), - (float)size / 1024 / 1024, - duration); + (int)(offset / 4 / 1024 / 1024), + (int)(offset % (4 * 1024 * 1024) / GZFILE_READ_CHUNK_SIZE), + (float)size / 1024 / 1024, + duration); + } return copied; } @@ -481,8 +488,25 @@ void GzippedFileReader::Close() if (m_src) { fclose(m_src); - m_src = 0; + m_src = nullptr; } AsyncPrefetchClose(); } + +u32 GzippedFileReader::GetBlockCount() const +{ + // type and formula copied from FlatFileReader + // FIXME? : Shouldn't it be uint and (size - m_dataoffset) / m_blocksize ? + return (int)((m_pIndex ? m_pIndex->uncompressed_size : 0) / m_blocksize); +} + +void GzippedFileReader::SetBlockSize(u32 bytes) +{ + m_blocksize = bytes; +} + +void GzippedFileReader::SetDataOffset(u32 bytes) +{ + m_dataoffset = bytes; +} diff --git a/pcsx2/CDVD/GzippedFileReader.h b/pcsx2/CDVD/GzippedFileReader.h index 47641789fa..1d0d48e429 100644 --- a/pcsx2/CDVD/GzippedFileReader.h +++ b/pcsx2/CDVD/GzippedFileReader.h @@ -1,59 +1,53 @@ /* PCSX2 - PS2 Emulator for PCs -* Copyright (C) 2002-2014 PCSX2 Dev Team -* -* PCSX2 is free software: you can redistribute it and/or modify it under the terms -* of the GNU Lesser General Public License as published by the Free Software Found- -* ation, either version 3 of the License, or (at your option) any later version. -* -* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -* PURPOSE. See the GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License along with PCSX2. -* If not, see . -*/ + * Copyright (C) 2002-2023 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ #pragma once -typedef struct zstate Zstate; - #include "AsyncFileReader.h" #include "ChunksCache.h" #include "zlib_indexed.h" -#define GZFILE_SPAN_DEFAULT (1048576L * 4) /* distance between direct access points when creating a new index */ -#define GZFILE_READ_CHUNK_SIZE (256 * 1024) /* zlib extraction chunks size (at 0-based boundaries) */ -#define GZFILE_CACHE_SIZE_MB 200 /* cache size for extracted data. must be at least GZFILE_READ_CHUNK_SIZE (in MB)*/ +static constexpr int GZFILE_SPAN_DEFAULT = (1048576 * 4); /* distance between direct access points when creating a new index */ +static constexpr int GZFILE_READ_CHUNK_SIZE = (256 * 1024); /* zlib extraction chunks size (at 0-based boundaries) */ +static constexpr int GZFILE_CACHE_SIZE_MB = 200; /* cache size for extracted data. must be at least GZFILE_READ_CHUNK_SIZE (in MB)*/ -class GzippedFileReader : public AsyncFileReader +typedef struct zstate Zstate; + +class GzippedFileReader final : public AsyncFileReader { DeclareNoncopyableObject(GzippedFileReader); public: - GzippedFileReader(void); - - virtual ~GzippedFileReader(void) { Close(); }; + GzippedFileReader(); + ~GzippedFileReader();; static bool CanHandle(const std::string& fileName, const std::string& displayName); - virtual bool Open(std::string fileName); + bool Open(std::string filename, Error* error) override; - virtual int ReadSync(void* pBuffer, uint sector, uint count); + int ReadSync(void* pBuffer, u32 sector, u32 count) override; - virtual void BeginRead(void* pBuffer, uint sector, uint count); - virtual int FinishRead(void); - virtual void CancelRead(void){}; + void BeginRead(void* pBuffer, u32 sector, u32 count); + int FinishRead(); + void CancelRead(); - virtual void Close(void); + void Close() override; - virtual uint GetBlockCount(void) const - { - // type and formula copied from FlatFileReader - // FIXME? : Shouldn't it be uint and (size - m_dataoffset) / m_blocksize ? - return (int)((m_pIndex ? m_pIndex->uncompressed_size : 0) / m_blocksize); - }; + u32 GetBlockCount() const; - virtual void SetBlockSize(uint bytes) { m_blocksize = bytes; } - virtual void SetDataOffset(int bytes) { m_dataoffset = bytes; } + void SetBlockSize(u32 bytes) override; + void SetDataOffset(u32 bytes) override; private: class Czstate @@ -70,23 +64,23 @@ private: Zstate state; }; - bool OkIndex(); // Verifies that we have an index, or try to create one + bool OkIndex(Error* error); // Verifies that we have an index, or try to create one s64 GetOptimalExtractionStart(s64 offset); int _ReadSync(void* pBuffer, s64 offset, uint bytesToRead); void InitZstates(); - int mBytesRead; // Temp sync read result when simulating async read - Access* m_pIndex; // Quick access index - Czstate* m_zstates; - FILE* m_src; + int mBytesRead = 0; // Temp sync read result when simulating async read + Access* m_pIndex = nullptr; // Quick access index + Czstate* m_zstates = nullptr; + FILE* m_src = nullptr; ChunksCache m_cache; #ifdef _WIN32 // Used by async prefetch - HANDLE hOverlappedFile; - OVERLAPPED asyncOperationContext; - bool asyncInProgress; + HANDLE hOverlappedFile = INVALID_HANDLE_VALUE; + OVERLAPPED asyncOperationContext = {}; + bool asyncInProgress = false; char mDummyAsyncPrefetchTarget[GZFILE_READ_CHUNK_SIZE]; #endif diff --git a/pcsx2/CDVD/InputIsoFile.cpp b/pcsx2/CDVD/InputIsoFile.cpp index ec232375a2..dacb8b11dd 100644 --- a/pcsx2/CDVD/InputIsoFile.cpp +++ b/pcsx2/CDVD/InputIsoFile.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -21,6 +21,7 @@ #include "Host.h" #include "common/Assertions.h" +#include "common/Error.h" #include "fmt/format.h" @@ -198,10 +199,10 @@ void InputIsoFile::_init() bool InputIsoFile::Test(std::string srcfile) { Close(); - return Open(std::move(srcfile), true); + return Open(std::move(srcfile), nullptr, true); } -bool InputIsoFile::Open(std::string srcfile, bool testOnly) +bool InputIsoFile::Open(std::string srcfile, Error* error, bool testOnly) { Close(); m_filename = std::move(srcfile); @@ -222,7 +223,7 @@ bool InputIsoFile::Open(std::string srcfile, bool testOnly) m_reader = new FlatFileReader(EmuConfig.CdvdShareWrite); } - if (!m_reader->Open(m_filename)) + if (!m_reader->Open(m_filename, error)) return false; // It might actually be a blockdump file. @@ -233,7 +234,7 @@ bool InputIsoFile::Open(std::string srcfile, bool testOnly) delete m_reader; BlockdumpFileReader* bdr = new BlockdumpFileReader(); - bdr->Open(m_filename); + bdr->Open(m_filename, error); m_blockofs = bdr->GetBlockOffset(); m_blocksize = bdr->GetBlockSize(); @@ -253,7 +254,7 @@ bool InputIsoFile::Open(std::string srcfile, bool testOnly) if (!detected) { - Console.Error(fmt::format("Unable to identify the ISO image type for '{}'", m_filename)); + Error::SetString(error, fmt::format("Unable to identify the ISO image type for '{}'", m_filename)); Close(); return false; } diff --git a/pcsx2/CDVD/IsoFileFormats.h b/pcsx2/CDVD/IsoFileFormats.h index 02e6836c27..d919c8d2c6 100644 --- a/pcsx2/CDVD/IsoFileFormats.h +++ b/pcsx2/CDVD/IsoFileFormats.h @@ -21,6 +21,8 @@ #include #include +class Error; + enum isoType { ISOTYPE_ILLEGAL = 0, @@ -35,7 +37,7 @@ static const int CD_FRAMESIZE_RAW = 2448; // -------------------------------------------------------------------------------------- // isoFile // -------------------------------------------------------------------------------------- -class InputIsoFile +class InputIsoFile final { DeclareNoncopyableObject(InputIsoFile); @@ -67,7 +69,7 @@ protected: public: InputIsoFile(); - virtual ~InputIsoFile(); + ~InputIsoFile(); bool IsOpened() const; @@ -81,7 +83,7 @@ public: } bool Test(std::string srcfile); - bool Open(std::string srcfile, bool testOnly = false); + bool Open(std::string srcfile, Error* error, bool testOnly); void Close(); bool Detect(bool readType = true); @@ -97,7 +99,7 @@ protected: void FindParts(); }; -class OutputIsoFile +class OutputIsoFile final { DeclareNoncopyableObject(OutputIsoFile); @@ -120,7 +122,7 @@ protected: public: OutputIsoFile(); - virtual ~OutputIsoFile(); + ~OutputIsoFile(); bool IsOpened() const; u32 GetBlockSize() const; diff --git a/pcsx2/CDVD/IsoHasher.cpp b/pcsx2/CDVD/IsoHasher.cpp index 44cb9cb024..d6ba96c35d 100644 --- a/pcsx2/CDVD/IsoHasher.cpp +++ b/pcsx2/CDVD/IsoHasher.cpp @@ -56,12 +56,9 @@ bool IsoHasher::Open(std::string iso_path, Error* error) CDVDsys_SetFile(CDVD_SourceType::Iso, std::move(iso_path)); CDVDsys_ChangeSource(CDVD_SourceType::Iso); - m_is_open = DoCDVDopen(); + m_is_open = DoCDVDopen(error); if (!m_is_open) - { - Error::SetString(error, "Failed to open CDVD."); return false; - } const s32 type = DoCDVDdetectDiskType(); switch (type) diff --git a/pcsx2/CDVD/Linux/IOCtlSrc.cpp b/pcsx2/CDVD/Linux/IOCtlSrc.cpp index 311ba1a1c6..5944e7900d 100644 --- a/pcsx2/CDVD/Linux/IOCtlSrc.cpp +++ b/pcsx2/CDVD/Linux/IOCtlSrc.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2020 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -17,6 +17,8 @@ #include "CDVD/CDVDdiscReader.h" #include "CDVD/CDVD.h" +#include "common/Error.h" + #include #include #include @@ -40,7 +42,7 @@ IOCtlSrc::~IOCtlSrc() } } -bool IOCtlSrc::Reopen() +bool IOCtlSrc::Reopen(Error* error) { if (m_device != -1) close(m_device); @@ -49,7 +51,10 @@ bool IOCtlSrc::Reopen() // drive is empty. Probably does other things too. m_device = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK); if (m_device == -1) + { + Error::SetErrno(error, errno); return false; + } // DVD detection MUST be first on Linux - The TOC ioctls work for both // CDs and DVDs. @@ -211,7 +216,7 @@ bool IOCtlSrc::DiscReady() if (ioctl(m_device, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK) { if (!m_sectors) - Reopen(); + Reopen(nullptr); } else { diff --git a/pcsx2/CDVD/ThreadedFileReader.cpp b/pcsx2/CDVD/ThreadedFileReader.cpp index fc11748ec0..b3d6cd5f25 100644 --- a/pcsx2/CDVD/ThreadedFileReader.cpp +++ b/pcsx2/CDVD/ThreadedFileReader.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2021 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -256,13 +256,13 @@ bool ThreadedFileReader::TryCachedRead(void*& buffer, u64& offset, u32& size, co return allDone; } -bool ThreadedFileReader::Open(std::string fileName) +bool ThreadedFileReader::Open(std::string filename, Error* error) { CancelAndWaitUntilStopped(); - return Open2(std::move(fileName)); + return Open2(std::move(filename), error); } -int ThreadedFileReader::ReadSync(void* pBuffer, uint sector, uint count) +int ThreadedFileReader::ReadSync(void* pBuffer, u32 sector, u32 count) { u32 blocksize = InternalBlockSize(); u64 offset = (u64)sector * (u64)blocksize + m_dataoffset; @@ -316,7 +316,7 @@ void ThreadedFileReader::CancelAndWaitUntilStopped(void) m_condition.wait(lock); } -void ThreadedFileReader::BeginRead(void* pBuffer, uint sector, uint count) +void ThreadedFileReader::BeginRead(void* pBuffer, u32 sector, u32 count) { s32 blocksize = InternalBlockSize(); u64 offset = (u64)sector * (u64)blocksize + m_dataoffset; @@ -371,12 +371,12 @@ void ThreadedFileReader::Close(void) Close2(); } -void ThreadedFileReader::SetBlockSize(uint bytes) +void ThreadedFileReader::SetBlockSize(u32 bytes) { m_blocksize = bytes; } -void ThreadedFileReader::SetDataOffset(int bytes) +void ThreadedFileReader::SetDataOffset(u32 bytes) { m_dataoffset = bytes; } diff --git a/pcsx2/CDVD/ThreadedFileReader.h b/pcsx2/CDVD/ThreadedFileReader.h index b45771beac..8bbece7630 100644 --- a/pcsx2/CDVD/ThreadedFileReader.h +++ b/pcsx2/CDVD/ThreadedFileReader.h @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2021 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -46,9 +46,9 @@ protected: /// Synchronously read the given block into `dst` virtual int ReadChunk(void* dst, s64 chunkID) = 0; /// AsyncFileReader open but ThreadedFileReader needs prep work first - virtual bool Open2(std::string fileName) = 0; + virtual bool Open2(std::string filename, Error* error) = 0; /// AsyncFileReader close but ThreadedFileReader needs prep work first - virtual void Close2(void) = 0; + virtual void Close2() = 0; ThreadedFileReader(); ~ThreadedFileReader(); @@ -108,12 +108,12 @@ private: bool TryCachedRead(void*& buffer, u64& offset, u32& size, const std::lock_guard&); public: - bool Open(std::string fileName) final override; - int ReadSync(void* pBuffer, uint sector, uint count) final override; - void BeginRead(void* pBuffer, uint sector, uint count) final override; - int FinishRead(void) final override; - void CancelRead(void) final override; - void Close(void) final override; - void SetBlockSize(uint bytes) final override; - void SetDataOffset(int bytes) final override; + bool Open(std::string filename, Error* error) final override; + int ReadSync(void* pBuffer, u32 sector, u32 count) final override; + void BeginRead(void* pBuffer, u32 sector, u32 count) final override; + int FinishRead() final override; + void CancelRead() final override; + void Close() final override; + void SetBlockSize(u32 bytes) final override; + void SetDataOffset(u32 bytes) final override; }; diff --git a/pcsx2/CDVD/Windows/IOCtlSrc.cpp b/pcsx2/CDVD/Windows/IOCtlSrc.cpp index 9917751e98..b2dbc3f6e8 100644 --- a/pcsx2/CDVD/Windows/IOCtlSrc.cpp +++ b/pcsx2/CDVD/Windows/IOCtlSrc.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2020 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -16,7 +16,9 @@ #include "PrecompiledHeader.h" #include "CDVD/CDVDdiscReader.h" #include "CDVD/CDVD.h" + #include "common/Console.h" +#include "common/Error.h" #include #include @@ -49,7 +51,7 @@ IOCtlSrc::~IOCtlSrc() // If a new disc is inserted, ReadFile will fail unless the device is closed // and reopened. -bool IOCtlSrc::Reopen() +bool IOCtlSrc::Reopen(Error* error) { if (m_device != INVALID_HANDLE_VALUE) CloseHandle(m_device); @@ -59,7 +61,10 @@ bool IOCtlSrc::Reopen() FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr); if (m_device == INVALID_HANDLE_VALUE) + { + Error::SetWin32(error, GetLastError()); return false; + } DWORD unused; // Required to read from layer 1 of Dual layer DVDs @@ -321,7 +326,7 @@ bool IOCtlSrc::DiscReady() nullptr, 0, &unused, nullptr)) { if (!m_sectors) - Reopen(); + Reopen(nullptr); } else { diff --git a/pcsx2/Darwin/DarwinFlatFileReader.cpp b/pcsx2/Darwin/DarwinFlatFileReader.cpp index 700bf5e9c8..e165bd35fe 100644 --- a/pcsx2/Darwin/DarwinFlatFileReader.cpp +++ b/pcsx2/Darwin/DarwinFlatFileReader.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2014 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -15,7 +15,9 @@ #include "PrecompiledHeader.h" #include "AsyncFileReader.h" + #include "common/FileSystem.h" + #include #include @@ -27,34 +29,35 @@ #warning AIO has been disabled. #endif -FlatFileReader::FlatFileReader(bool shareWrite) : shareWrite(shareWrite) +FlatFileReader::FlatFileReader(bool shareWrite) + : shareWrite(shareWrite) { m_blocksize = 2048; m_fd = -1; m_async_read_in_progress = false; } -FlatFileReader::~FlatFileReader(void) +FlatFileReader::~FlatFileReader() { Close(); } -bool FlatFileReader::Open(std::string fileName) +bool FlatFileReader::Open(std::string filename, Error* error) { - m_filename = std::move(fileName); + m_filename = std::move(filename); - m_fd = FileSystem::OpenFDFile(m_filename.c_str(), O_RDONLY, 0); + m_fd = FileSystem::OpenFDFile(m_filename.c_str(), O_RDONLY, 0, error); return (m_fd != -1); } -int FlatFileReader::ReadSync(void* pBuffer, uint sector, uint count) +int FlatFileReader::ReadSync(void* pBuffer, u32 sector, u32 count) { BeginRead(pBuffer, sector, count); return FinishRead(); } -void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count) +void FlatFileReader::BeginRead(void* pBuffer, u32 sector, u32 count) { u64 offset = sector * (u64)m_blocksize + m_dataoffset; @@ -98,20 +101,20 @@ void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count) } } -int FlatFileReader::FinishRead(void) +int FlatFileReader::FinishRead() { if (!m_async_read_in_progress) return m_aiocb.aio_nbytes == (size_t)-1 ? -1 : 1; m_async_read_in_progress = true; - struct aiocb *aiocb_list[] = {&m_aiocb}; + struct aiocb* aiocb_list[] = {&m_aiocb}; while (aio_suspend(aiocb_list, 1, nullptr) == -1 && errno == EINTR) ; return aio_return(&m_aiocb); } -void FlatFileReader::CancelRead(void) +void FlatFileReader::CancelRead() { if (m_async_read_in_progress) { @@ -120,7 +123,7 @@ void FlatFileReader::CancelRead(void) } } -void FlatFileReader::Close(void) +void FlatFileReader::Close() { CancelRead(); if (m_fd != -1) @@ -129,7 +132,7 @@ void FlatFileReader::Close(void) m_fd = -1; } -uint FlatFileReader::GetBlockCount(void) const +u32 FlatFileReader::GetBlockCount() const { - return (int)(FileSystem::GetPathFileSize(m_filename.c_str()) / m_blocksize); + return static_cast(FileSystem::GetPathFileSize(m_filename.c_str()) / m_blocksize); } diff --git a/pcsx2/GameList.cpp b/pcsx2/GameList.cpp index c0ce8dd0c6..eb9e46ac26 100644 --- a/pcsx2/GameList.cpp +++ b/pcsx2/GameList.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2023 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -25,6 +25,7 @@ #include "common/Assertions.h" #include "common/Console.h" #include "common/FileSystem.h" +#include "common/Error.h" #include "common/HTTPDownloader.h" #include "common/HeterogeneousContainers.h" #include "common/Path.h" @@ -171,10 +172,15 @@ void GameList::FillBootParametersForEntry(VMBootParameters* params, const Entry* bool GameList::GetIsoSerialAndCRC(const std::string& path, s32* disc_type, std::string* serial, u32* crc) { + Error error; + // This isn't great, we really want to make it all thread-local... CDVD = &CDVDapi_Iso; - if (CDVD->open(path.c_str()) != 0) + if (!CDVD->open(path, &error)) + { + Console.Error(fmt::format("(GameList::GetIsoSerialAndCRC) CDVD open of '{}' failed: {}", path, error.GetDescription())); return false; + } // TODO: we could include the version in the game list? *disc_type = DoCDVDdetectDiskType(); diff --git a/pcsx2/Linux/LnxFlatFileReader.cpp b/pcsx2/Linux/LnxFlatFileReader.cpp index a37082c35a..add2e738c2 100644 --- a/pcsx2/Linux/LnxFlatFileReader.cpp +++ b/pcsx2/Linux/LnxFlatFileReader.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2014 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -15,6 +15,7 @@ #include "PrecompiledHeader.h" #include "AsyncFileReader.h" + #include "common/FileSystem.h" #include @@ -29,31 +30,31 @@ FlatFileReader::FlatFileReader(bool shareWrite) m_aio_context = 0; } -FlatFileReader::~FlatFileReader(void) +FlatFileReader::~FlatFileReader() { Close(); } -bool FlatFileReader::Open(std::string fileName) +bool FlatFileReader::Open(std::string filename, Error* error) { - m_filename = std::move(fileName); + m_filename = std::move(filename); int err = io_setup(64, &m_aio_context); if (err) return false; - m_fd = FileSystem::OpenFDFile(m_filename.c_str(), O_RDONLY, 0); + m_fd = FileSystem::OpenFDFile(m_filename.c_str(), O_RDONLY, 0, error); return (m_fd != -1); } -int FlatFileReader::ReadSync(void* pBuffer, uint sector, uint count) +int FlatFileReader::ReadSync(void* pBuffer, u32 sector, u32 count) { BeginRead(pBuffer, sector, count); return FinishRead(); } -void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count) +void FlatFileReader::BeginRead(void* pBuffer, u32 sector, u32 count) { u64 offset; offset = sector * (s64)m_blocksize + m_dataoffset; @@ -67,7 +68,7 @@ void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count) io_submit(m_aio_context, 1, &iocbs); } -int FlatFileReader::FinishRead(void) +int FlatFileReader::FinishRead() { struct io_event event; @@ -78,7 +79,7 @@ int FlatFileReader::FinishRead(void) return event.res; } -void FlatFileReader::CancelRead(void) +void FlatFileReader::CancelRead() { // Will be done when m_aio_context context is destroyed // Note: io_cancel exists but need the iocb structure as parameter @@ -86,7 +87,7 @@ void FlatFileReader::CancelRead(void) // struct io_event *result); } -void FlatFileReader::Close(void) +void FlatFileReader::Close() { if (m_fd != -1) close(m_fd); @@ -97,11 +98,11 @@ void FlatFileReader::Close(void) m_aio_context = 0; } -uint FlatFileReader::GetBlockCount(void) const +u32 FlatFileReader::GetBlockCount() const { struct stat sysStatData; if (fstat(m_fd, &sysStatData) < 0) return 0; - return static_cast(sysStatData.st_size / m_blocksize); + return static_cast(sysStatData.st_size / m_blocksize); } diff --git a/pcsx2/MultipartFileReader.cpp b/pcsx2/MultipartFileReader.cpp index 14d1bcdc56..f1c8886f5b 100644 --- a/pcsx2/MultipartFileReader.cpp +++ b/pcsx2/MultipartFileReader.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2014 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -15,8 +15,10 @@ #include "PrecompiledHeader.h" #include "AsyncFileReader.h" + #include "common/Assertions.h" #include "common/FileSystem.h" +#include "common/Error.h" #include "common/Path.h" #include "common/StringUtil.h" @@ -120,7 +122,7 @@ void MultipartFileReader::FindParts() Part* thispart = m_parts + m_numparts; AsyncFileReader* thisreader = new FlatFileReader(); - if (!thisreader->Open(nameparts)) + if (!thisreader->Open(nameparts, nullptr)) { delete thisreader; break; @@ -147,8 +149,9 @@ void MultipartFileReader::FindParts() //Console.WriteLn( Color_Blue, "isoFile: multi-part ISO loaded (%u parts found)", m_numparts ); } -bool MultipartFileReader::Open(std::string fileName) +bool MultipartFileReader::Open(std::string filename, Error* error) { + Error::SetString(error, "Cannot open a MultipartFileReader directly."); // Cannot open a MultipartFileReader directly, // use DetectMultipart to convert a FlatFileReader return false; diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 7b0b271f68..02aac482b6 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -1142,10 +1142,13 @@ bool VMManager::Initialize(VMBootParameters boot_params) } } + Error error; Console.WriteLn("Opening CDVD..."); - if (!DoCDVDopen()) + if (!DoCDVDopen(&error)) { - Host::ReportErrorAsync("Startup Error", "Failed to initialize CDVD."); + Host::ReportErrorAsync("Startup Error", fmt::format("Failed to open CDVD '{}': {}.", + Path::GetFileName(CDVDsys_GetFile(CDVDsys_GetSourceType())), + error.GetDescription())); return false; } ScopedGuard close_cdvd(&DoCDVDclose); @@ -1909,7 +1912,8 @@ bool VMManager::ChangeDisc(CDVD_SourceType source, std::string path) if (!path.empty()) CDVDsys_SetFile(source, std::move(path)); - const bool result = DoCDVDopen(); + Error error; + const bool result = DoCDVDopen(&error); if (result) { if (source == CDVD_SourceType::NoDisc) @@ -1927,18 +1931,20 @@ bool VMManager::ChangeDisc(CDVD_SourceType source, std::string path) { Host::AddIconOSDMessage("ChangeDisc", ICON_FA_COMPACT_DISC, fmt::format( - TRANSLATE_FS("VMManager", "Failed to open new disc image '{}'. Reverting to old image."), display_name), + TRANSLATE_FS("VMManager", "Failed to open new disc image '{}'. Reverting to old image.\nError was: {}"), + display_name, error.GetDescription()), Host::OSD_ERROR_DURATION); CDVDsys_ChangeSource(old_type); if (!old_path.empty()) CDVDsys_SetFile(old_type, std::move(old_path)); - if (!DoCDVDopen()) + if (!DoCDVDopen(&error)) { Host::AddIconOSDMessage("ChangeDisc", ICON_FA_COMPACT_DISC, - TRANSLATE_SV("VMManager", "Failed to switch back to old disc image. Removing disc."), + fmt::format(TRANSLATE_FS("VMManager", "Failed to switch back to old disc image. Removing disc.\nError was: {}"), + error.GetDescription()), Host::OSD_CRITICAL_ERROR_DURATION); CDVDsys_ChangeSource(CDVD_SourceType::NoDisc); - DoCDVDopen(); + DoCDVDopen(nullptr); } } cdvd.Tray.cdvdActionSeconds = 1; diff --git a/pcsx2/windows/FlatFileReaderWindows.cpp b/pcsx2/windows/FlatFileReaderWindows.cpp index 5e45e656ae..f62463c46c 100644 --- a/pcsx2/windows/FlatFileReaderWindows.cpp +++ b/pcsx2/windows/FlatFileReaderWindows.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2014 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -15,7 +15,9 @@ #include "PrecompiledHeader.h" #include "AsyncFileReader.h" + #include "common/StringUtil.h" +#include "common/Error.h" FlatFileReader::FlatFileReader(bool shareWrite) : shareWrite(shareWrite) { @@ -25,14 +27,14 @@ FlatFileReader::FlatFileReader(bool shareWrite) : shareWrite(shareWrite) asyncInProgress = false; } -FlatFileReader::~FlatFileReader(void) +FlatFileReader::~FlatFileReader() { Close(); } -bool FlatFileReader::Open(std::string fileName) +bool FlatFileReader::Open(std::string filename, Error* error) { - m_filename = std::move(fileName); + m_filename = std::move(filename); hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); @@ -49,10 +51,16 @@ bool FlatFileReader::Open(std::string fileName) FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED, NULL); - return hOverlappedFile != INVALID_HANDLE_VALUE; + if (hOverlappedFile == INVALID_HANDLE_VALUE) + { + Error::SetWin32(error, GetLastError()); + return false; + } + + return true; } -int FlatFileReader::ReadSync(void* pBuffer, uint sector, uint count) +int FlatFileReader::ReadSync(void* pBuffer, u32 sector, u32 count) { //LARGE_INTEGER offset; //offset.QuadPart = sector * (__int64)m_blocksize; @@ -68,7 +76,7 @@ int FlatFileReader::ReadSync(void* pBuffer, uint sector, uint count) return FinishRead(); } -void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count) +void FlatFileReader::BeginRead(void* pBuffer, u32 sector, u32 count) { LARGE_INTEGER offset; offset.QuadPart = sector * (s64)m_blocksize + m_dataoffset; @@ -84,7 +92,7 @@ void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count) asyncInProgress = true; } -int FlatFileReader::FinishRead(void) +int FlatFileReader::FinishRead() { DWORD bytes; @@ -98,12 +106,12 @@ int FlatFileReader::FinishRead(void) return bytes; } -void FlatFileReader::CancelRead(void) +void FlatFileReader::CancelRead() { CancelIo(hOverlappedFile); } -void FlatFileReader::Close(void) +void FlatFileReader::Close() { if(asyncInProgress) CancelRead(); @@ -118,10 +126,10 @@ void FlatFileReader::Close(void) hEvent = INVALID_HANDLE_VALUE; } -uint FlatFileReader::GetBlockCount(void) const +u32 FlatFileReader::GetBlockCount(void) const { LARGE_INTEGER fileSize; - fileSize.LowPart = GetFileSize(hOverlappedFile, (DWORD*)&(fileSize.HighPart)); + fileSize.LowPart = GetFileSize(hOverlappedFile, reinterpret_cast(&fileSize.HighPart)); - return (int)(fileSize.QuadPart / m_blocksize); + return static_cast(fileSize.QuadPart / m_blocksize); }