CDVD: Report open errors to host

This commit is contained in:
Stenzek 2023-10-01 01:20:53 +10:00 committed by Connor McLaughlin
parent 93a4e67813
commit a9959bcd62
29 changed files with 592 additions and 547 deletions

View File

@ -97,8 +97,6 @@ static constexpr unsigned int __pagemask = __pagesize - 1;
#define likely(x) (!!(x)) #define likely(x) (!!(x))
#define unlikely(x) (!!(x)) #define unlikely(x) (!!(x))
#define CALLBACK __stdcall
#else #else
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -110,9 +108,6 @@ static constexpr unsigned int __pagemask = __pagesize - 1;
// SysV ABI passes vector parameters through registers unconditionally. // SysV ABI passes vector parameters through registers unconditionally.
#ifndef _WIN32 #ifndef _WIN32
#define __vectorcall #define __vectorcall
#define CALLBACK
#else
#define CALLBACK __attribute__((stdcall))
#endif #endif
// Inlining note: GCC needs ((unused)) attributes defined on inlined functions to suppress // Inlining note: GCC needs ((unused)) attributes defined on inlined functions to suppress

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -16,54 +16,56 @@
#pragma once #pragma once
#ifdef _WIN32 #ifdef _WIN32
# include "common/RedtapeWindows.h" #include "common/RedtapeWindows.h"
#elif defined(__linux__) #elif defined(__linux__)
# include <libaio.h> #include <libaio.h>
#elif defined(__POSIX__) #elif defined(__POSIX__)
# include <aio.h> #include <aio.h>
#endif #endif
#include <memory> #include <memory>
#include <string> #include <string>
class Error;
class AsyncFileReader class AsyncFileReader
{ {
protected: protected:
AsyncFileReader() : m_dataoffset(0), m_blocksize(0) {} AsyncFileReader()
: m_dataoffset(0)
, m_blocksize(0)
{
}
std::string m_filename; std::string m_filename;
int m_dataoffset; u32 m_dataoffset;
uint m_blocksize; u32 m_blocksize;
public: 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 void BeginRead(void* pBuffer, u32 sector, u32 count) = 0;
virtual int FinishRead(void)=0; virtual int FinishRead() = 0;
virtual void CancelRead(void)=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 SetBlockSize(u32 bytes) {}
virtual void SetDataOffset(int bytes) {} virtual void SetDataOffset(u32 bytes) {}
uint GetBlockSize() const { return m_blocksize; } const std::string& GetFilename() const { return m_filename; }
u32 GetBlockSize() const { return m_blocksize; }
const std::string& GetFilename() const
{
return m_filename;
}
}; };
class FlatFileReader : public AsyncFileReader class FlatFileReader final : public AsyncFileReader
{ {
DeclareNoncopyableObject( FlatFileReader ); DeclareNoncopyableObject(FlatFileReader);
#ifdef _WIN32 #ifdef _WIN32
HANDLE hOverlappedFile; HANDLE hOverlappedFile;
@ -86,65 +88,66 @@ class FlatFileReader : public AsyncFileReader
public: public:
FlatFileReader(bool shareWrite = false); 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; void BeginRead(void* pBuffer, u32 sector, u32 count) override;
virtual int FinishRead(void) override; int FinishRead() override;
virtual void CancelRead(void) 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; } void SetBlockSize(u32 bytes) override { m_blocksize = bytes; }
virtual void SetDataOffset(int bytes) override { m_dataoffset = 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; static const int MaxParts = 8;
struct Part { struct Part
uint start; {
uint end; // exclusive u32 start;
u32 end; // exclusive
bool isReading; bool isReading;
AsyncFileReader* reader; AsyncFileReader* reader;
} m_parts[MaxParts]; } m_parts[MaxParts];
uint m_numparts; u32 m_numparts;
uint GetFirstPart(uint lsn); u32 GetFirstPart(u32 lsn);
void FindParts(); void FindParts();
public: public:
MultipartFileReader(AsyncFileReader* firstPart); 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; void BeginRead(void* pBuffer, u32 sector, u32 count) override;
virtual int FinishRead(void) override; int FinishRead() override;
virtual void CancelRead(void) 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); static AsyncFileReader* DetectMultipart(AsyncFileReader* reader);
}; };
class BlockdumpFileReader : public AsyncFileReader class BlockdumpFileReader : public AsyncFileReader
{ {
DeclareNoncopyableObject( BlockdumpFileReader ); DeclareNoncopyableObject(BlockdumpFileReader);
std::FILE* m_file; std::FILE* m_file;
@ -160,21 +163,21 @@ class BlockdumpFileReader : public AsyncFileReader
public: public:
BlockdumpFileReader(); 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; void BeginRead(void* pBuffer, u32 sector, u32 count) override;
virtual int FinishRead(void) override; int FinishRead() override;
virtual void CancelRead(void) 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); static bool DetectBlockdump(AsyncFileReader* reader);
int GetBlockOffset() { return m_blockofs; } s32 GetBlockOffset() { return m_blockofs; }
}; };

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -18,6 +18,7 @@
#include "IsoFileFormats.h" #include "IsoFileFormats.h"
#include "common/Assertions.h" #include "common/Assertions.h"
#include "common/FileSystem.h" #include "common/FileSystem.h"
#include "common/Error.h"
#include <errno.h> #include <errno.h>
@ -27,11 +28,11 @@ enum isoFlags
ISOFLAGS_BLOCKDUMP_V3 = 0x0020 ISOFLAGS_BLOCKDUMP_V3 = 0x0020
}; };
static const uint BlockDumpHeaderSize = 16; static constexpr u32 BlockDumpHeaderSize = 16;
bool BlockdumpFileReader::DetectBlockdump(AsyncFileReader* reader) bool BlockdumpFileReader::DetectBlockdump(AsyncFileReader* reader)
{ {
uint oldbs = reader->GetBlockSize(); u32 oldbs = reader->GetBlockSize();
reader->SetBlockSize(1); reader->SetBlockSize(1);
@ -45,7 +46,7 @@ bool BlockdumpFileReader::DetectBlockdump(AsyncFileReader* reader)
return isbd; return isbd;
} }
BlockdumpFileReader::BlockdumpFileReader(void) BlockdumpFileReader::BlockdumpFileReader()
: m_file(NULL) : m_file(NULL)
, m_blocks(0) , m_blocks(0)
, m_blockofs(0) , m_blockofs(0)
@ -54,19 +55,22 @@ BlockdumpFileReader::BlockdumpFileReader(void)
{ {
} }
BlockdumpFileReader::~BlockdumpFileReader(void) BlockdumpFileReader::~BlockdumpFileReader()
{ {
Close(); Close();
} }
bool BlockdumpFileReader::Open(std::string fileName) bool BlockdumpFileReader::Open(std::string filename, Error* error)
{ {
char signature[4]; char signature[4];
m_filename = std::move(fileName); m_filename = std::move(filename);
m_file = FileSystem::OpenCFile(m_filename.c_str(), "rb"); if (!(m_file = FileSystem::OpenCFile(m_filename.c_str(), "rb", error)))
if (!m_file || std::fread(signature, sizeof(signature), 1, m_file) != 1 || std::memcmp(signature, "BDV2", sizeof(signature)) != 0) 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; 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_blocks, sizeof(m_blocks), 1, m_file) != 1
|| std::fread(&m_blockofs, sizeof(m_blockofs), 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; return false;
} }
@ -87,7 +92,10 @@ bool BlockdumpFileReader::Open(std::string fileName)
m_dtable = std::make_unique<u32[]>(m_dtablesize); m_dtable = std::make_unique<u32[]>(m_dtablesize);
if (FileSystem::FSeek64(m_file, BlockDumpHeaderSize, SEEK_SET) != 0) if (FileSystem::FSeek64(m_file, BlockDumpHeaderSize, SEEK_SET) != 0)
{
Error::SetString(error, "Failed to seek to block dump data.");
return false; return false;
}
u32 bs = 1024 * 1024; u32 bs = 1024 * 1024;
u32 off = 0; u32 off = 0;
@ -112,7 +120,7 @@ bool BlockdumpFileReader::Open(std::string fileName)
return true; return true;
} }
int BlockdumpFileReader::ReadSync(void* pBuffer, uint lsn, uint count) int BlockdumpFileReader::ReadSync(void* pBuffer, u32 lsn, u32 count)
{ {
u8* dst = (u8*)pBuffer; u8* dst = (u8*)pBuffer;
// Console.WriteLn("_isoReadBlockD %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs); // 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; 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); m_lresult = ReadSync(pBuffer, sector, count);
} }
int BlockdumpFileReader::FinishRead(void) int BlockdumpFileReader::FinishRead()
{ {
return m_lresult; return m_lresult;
} }
void BlockdumpFileReader::CancelRead(void) void BlockdumpFileReader::CancelRead()
{ {
} }
@ -178,11 +186,11 @@ void BlockdumpFileReader::Close(void)
if (m_file) if (m_file)
{ {
std::fclose(m_file); std::fclose(m_file);
m_file = NULL; m_file = nullptr;
} }
} }
uint BlockdumpFileReader::GetBlockCount(void) const u32 BlockdumpFileReader::GetBlockCount() const
{ {
return m_blocks; return m_blocks;
} }

View File

@ -38,7 +38,7 @@
#define ENABLE_TIMESTAMPS #define ENABLE_TIMESTAMPS
CDVD_API* CDVD = nullptr; const CDVD_API* CDVD = nullptr;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// diskTypeCached // diskTypeCached
@ -327,7 +327,7 @@ void CDVDsys_ClearFiles()
void CDVDsys_ChangeSource(CDVD_SourceType type) void CDVDsys_ChangeSource(CDVD_SourceType type)
{ {
if (CDVD != NULL) if (CDVD)
DoCDVDclose(); DoCDVDclose();
switch (m_CurrentSourceType = type) switch (m_CurrentSourceType = type)
@ -348,15 +348,14 @@ void CDVDsys_ChangeSource(CDVD_SourceType type)
} }
} }
bool DoCDVDopen() bool DoCDVDopen(Error* error)
{ {
CheckNullCDVD(); CheckNullCDVD();
CDVD->newDiskCB(cdvdNewDiskCB); CDVD->newDiskCB(cdvdNewDiskCB);
auto CurrentSourceType = enum_cast(m_CurrentSourceType); auto CurrentSourceType = enum_cast(m_CurrentSourceType);
int ret = CDVD->open(!m_SourceFilename[CurrentSourceType].empty() ? m_SourceFilename[CurrentSourceType].c_str() : nullptr); if (!CDVD->open(m_SourceFilename[CurrentSourceType], error))
if (ret == -1)
return false; // error! (handled by caller) return false; // error! (handled by caller)
int cdtype = DoCDVDdetectDiskType(); int cdtype = DoCDVDdetectDiskType();
@ -428,8 +427,7 @@ void DoCDVDclose()
blockDumpFile.Close(); blockDumpFile.Close();
if (CDVD->close != NULL) CDVD->close();
CDVD->close();
DoCDVDresetDiskTypeCache(); 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; return -1;
} }
s32 CALLBACK NODISCgetBuffer(u8* buffer) static s32 NODISCgetBuffer(u8* buffer)
{ {
return -1; return -1;
} }
s32 CALLBACK NODISCreadSubQ(u32 lsn, cdvdSubQ* subq) static s32 NODISCreadSubQ(u32 lsn, cdvdSubQ* subq)
{ {
return -1; return -1;
} }
s32 CALLBACK NODISCgetTN(cdvdTN* Buffer) static s32 NODISCgetTN(cdvdTN* Buffer)
{ {
return -1; return -1;
} }
s32 CALLBACK NODISCgetTD(u8 Track, cdvdTD* Buffer) static s32 NODISCgetTD(u8 Track, cdvdTD* Buffer)
{ {
return -1; return -1;
} }
s32 CALLBACK NODISCgetTOC(void* toc) static s32 NODISCgetTOC(void* toc)
{ {
return -1; return -1;
} }
s32 CALLBACK NODISCgetDiskType() static s32 NODISCgetDiskType()
{ {
return CDVD_TYPE_NODISC; return CDVD_TYPE_NODISC;
} }
s32 CALLBACK NODISCgetTrayStatus() static s32 NODISCgetTrayStatus()
{ {
return CDVD_TRAY_CLOSE; return CDVD_TRAY_CLOSE;
} }
s32 CALLBACK NODISCdummyS32() static s32 NODISCdummyS32()
{ {
return 0; 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; return -1;
} }
s32 CALLBACK NODISCgetDualInfo(s32* dualType, u32* _layer1start) static s32 NODISCgetDualInfo(s32* dualType, u32* _layer1start)
{ {
return -1; return -1;
} }
CDVD_API CDVDapi_NoDisc = const CDVD_API CDVDapi_NoDisc =
{ {
NODISCclose, NODISCclose,
NODISCopen, NODISCopen,

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -16,19 +16,21 @@
#pragma once #pragma once
#include <string> #include <string>
class Error;
typedef struct _cdvdSubQ typedef struct _cdvdSubQ
{ {
u8 ctrl : 4; // control and mode bits u8 ctrl : 4; // control and mode bits
u8 mode : 4; // control and mode bits u8 mode : 4; // control and mode bits
u8 trackNum; // current track number (1 to 99) u8 trackNum; // current track number (1 to 99)
u8 trackIndex; // current index within track (0 to 99) u8 trackIndex; // current index within track (0 to 99)
u8 trackM; // current minute location on the disc (BCD encoded) u8 trackM; // current minute location on the disc (BCD encoded)
u8 trackS; // current sector 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 trackF; // current frame location on the disc (BCD encoded)
u8 pad; // unused u8 pad; // unused
u8 discM; // current minute offset from first track (BCD encoded) u8 discM; // current minute offset from first track (BCD encoded)
u8 discS; // current sector 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 discF; // current frame offset from first track (BCD encoded)
} cdvdSubQ; } cdvdSubQ;
typedef struct _cdvdTD typedef struct _cdvdTD
@ -44,9 +46,9 @@ typedef struct _cdvdTN
} cdvdTN; } cdvdTN;
// SpindleCtrl Masks // 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_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: // CDVDreadTrack mode values:
#define CDVD_MODE_2352 0 // full 2352 bytes #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 #define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq
// CDVDgetDiskType returns: // CDVDgetDiskType returns:
#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc #define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc
#define CDVD_TYPE_DVDV 0xfe // DVD Video #define CDVD_TYPE_DVDV 0xfe // DVD Video
#define CDVD_TYPE_CDDA 0xfd // Audio CD #define CDVD_TYPE_CDDA 0xfd // Audio CD
#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD #define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD
#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) #define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio)
#define CDVD_TYPE_PS2CD 0x12 // PS2 CD #define CDVD_TYPE_PS2CD 0x12 // PS2 CD
#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) #define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio)
#define CDVD_TYPE_PSCD 0x10 // PS CD #define CDVD_TYPE_PSCD 0x10 // PS CD
#define CDVD_TYPE_UNKNOWN 0x05 // Unknown #define CDVD_TYPE_UNKNOWN 0x05 // Unknown
#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided #define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided
#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided #define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided
#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd #define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd
#define CDVD_TYPE_DETCT 0x01 // Detecting #define CDVD_TYPE_DETCT 0x01 // Detecting
#define CDVD_TYPE_NODISC 0x00 // No Disc #define CDVD_TYPE_NODISC 0x00 // No Disc
// CDVDgetTrayStatus returns: // CDVDgetTrayStatus returns:
#define CDVD_TRAY_CLOSE 0x00 #define CDVD_TRAY_CLOSE 0x00
@ -85,44 +87,42 @@ typedef struct _cdvdTN
// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) // CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel)
// CDVD // CDVD
// NOTE: The read/write functions CANNOT use XMM/MMX regs typedef bool (*_CDVDopen)(std::string filename, Error* error);
// If you want to use them, need to save and restore current ones
typedef s32(CALLBACK* _CDVDopen)(const char* pTitleFilename);
// Initiates an asynchronous track read operation. // Initiates an asynchronous track read operation.
// Returns -1 on error (invalid track) // Returns -1 on error (invalid track)
// Returns 0 on success. // 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. // Copies loaded data to the target buffer.
// Returns -2 if the asynchronous read is still pending. // Returns -2 if the asynchronous read is still pending.
// Returns -1 if the asyncronous read failed. // Returns -1 if the asyncronous read failed.
// Returns 0 on success. // 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 (*_CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq);
typedef s32(CALLBACK* _CDVDgetTN)(cdvdTN* Buffer); typedef s32 (*_CDVDgetTN)(cdvdTN* Buffer);
typedef s32(CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD* Buffer); typedef s32 (*_CDVDgetTD)(u8 Track, cdvdTD* Buffer);
typedef s32(CALLBACK* _CDVDgetTOC)(void* toc); typedef s32 (*_CDVDgetTOC)(void* toc);
typedef s32(CALLBACK* _CDVDgetDiskType)(); typedef s32 (*_CDVDgetDiskType)();
typedef s32(CALLBACK* _CDVDgetTrayStatus)(); typedef s32 (*_CDVDgetTrayStatus)();
typedef s32(CALLBACK* _CDVDctrlTrayOpen)(); typedef s32 (*_CDVDctrlTrayOpen)();
typedef s32(CALLBACK* _CDVDctrlTrayClose)(); typedef s32 (*_CDVDctrlTrayClose)();
typedef s32(CALLBACK* _CDVDreadSector)(u8* buffer, u32 lsn, int mode); typedef s32 (*_CDVDreadSector)(u8* buffer, u32 lsn, int mode);
typedef s32(CALLBACK* _CDVDgetDualInfo)(s32* dualType, u32* _layer1start); typedef s32 (*_CDVDgetDualInfo)(s32* dualType, u32* _layer1start);
typedef void(CALLBACK* _CDVDnewDiskCB)(void (*callback)()); typedef void (*_CDVDnewDiskCB)(void (*callback)());
enum class CDVD_SourceType : uint8_t enum class CDVD_SourceType : uint8_t
{ {
Iso, // use built in ISO api Iso, // use built in ISO api
Disc, // use built in Disc api Disc, // use built in Disc api
NoDisc, // use built in CDVDnull NoDisc, // use built in CDVDnull
}; };
struct CDVD_API struct CDVD_API
{ {
void(CALLBACK* close)(); void (*close)();
// Don't need init or shutdown. iso/nodisc have no init/shutdown. // Don't need init or shutdown. iso/nodisc have no init/shutdown.
@ -148,11 +148,11 @@ struct CDVD_API
// Multiple interface system for CDVD. // 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 const CDVD_API CDVDapi_Iso;
extern CDVD_API CDVDapi_Disc; extern const CDVD_API CDVDapi_Disc;
extern CDVD_API CDVDapi_NoDisc; extern const CDVD_API CDVDapi_NoDisc;
extern void CDVDsys_ChangeSource(CDVD_SourceType type); extern void CDVDsys_ChangeSource(CDVD_SourceType type);
extern void CDVDsys_SetFile(CDVD_SourceType srctype, std::string newfile); 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 CDVD_SourceType CDVDsys_GetSourceType();
extern void CDVDsys_ClearFiles(); extern void CDVDsys_ClearFiles();
extern bool DoCDVDopen(); extern bool DoCDVDopen(Error* error);
extern void DoCDVDclose(); extern void DoCDVDclose();
extern s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode); extern s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode);
extern s32 DoCDVDreadTrack(u32 lsn, int mode); extern s32 DoCDVDreadTrack(u32 lsn, int mode);

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -17,6 +17,8 @@
#include "CDVDdiscReader.h" #include "CDVDdiscReader.h"
#include "CDVD/CDVD.h" #include "CDVD/CDVD.h"
#include "common/Error.h"
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
@ -41,19 +43,19 @@ int curTrayStatus;
static u32 csector; static u32 csector;
int cmode; int cmode;
int lastReadInNewDiskCB = 0; static int lastReadInNewDiskCB = 0;
u8 directReadSectorBuffer[2448]; static u8 directReadSectorBuffer[2448];
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Utility Functions // // Utility Functions //
inline u8 dec_to_bcd(u8 dec) static u8 dec_to_bcd(u8 dec)
{ {
return ((dec / 10) << 4) | (dec % 10); 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); *frame = dec_to_bcd(lsn % 75);
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 // // keepAliveThread throws a read event regularly to prevent drive spin down //
void keepAliveThread() static void keepAliveThread()
{ {
u8 throwaway[2352]; u8 throwaway[2352];
@ -175,29 +177,33 @@ void StopKeepAliveThread()
s_keepalive_thread.join(); 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); GetValidDrive(drive);
if (drive.empty()) if (drive.empty())
return -1; {
Error::SetString(error, fmt::format("Failed to get drive for {}", filename));
return false;
}
// open device file // open device file
src = std::make_unique<IOCtlSrc>(std::move(drive)); src = std::make_unique<IOCtlSrc>(std::move(drive));
if (!src->Reopen()) if (!src->Reopen(error))
{ {
src.reset(); src.reset();
return -1; return false;
} }
//setup threading manager //setup threading manager
cdvdStartThread(); cdvdStartThread();
StartKeepAliveThread(); StartKeepAliveThread();
return cdvdRefreshData(); cdvdRefreshData();
return true;
} }
void CALLBACK DISCclose() static void DISCclose()
{ {
StopKeepAliveThread(); StopKeepAliveThread();
cdvdStopThread(); cdvdStopThread();
@ -205,7 +211,7 @@ void CALLBACK DISCclose()
src.reset(); src.reset();
} }
s32 CALLBACK DISCreadTrack(u32 lsn, int mode) static s32 DISCreadTrack(u32 lsn, int mode)
{ {
csector = lsn; csector = lsn;
cmode = mode; cmode = mode;
@ -223,7 +229,7 @@ s32 CALLBACK DISCreadTrack(u32 lsn, int mode)
return 0; 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 // Do nothing for out of bounds disc sector reads. It prevents some games
// from hanging (All-Star Baseball 2005, Hello Kitty: Roller Rescue, // from hanging (All-Star Baseball 2005, Hello Kitty: Roller Rescue,
@ -259,7 +265,7 @@ s32 CALLBACK DISCgetBuffer(u8* dest)
return 0; 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 // 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; return 0;
} }
s32 CALLBACK DISCgetTN(cdvdTN* Buffer) static s32 DISCgetTN(cdvdTN* Buffer)
{ {
Buffer->strack = strack; Buffer->strack = strack;
Buffer->etrack = etrack; Buffer->etrack = etrack;
return 0; return 0;
} }
s32 CALLBACK DISCgetTD(u8 Track, cdvdTD* Buffer) static s32 DISCgetTD(u8 Track, cdvdTD* Buffer)
{ {
if (Track == 0) if (Track == 0)
{ {
@ -315,7 +321,7 @@ s32 CALLBACK DISCgetTD(u8 Track, cdvdTD* Buffer)
return 0; return 0;
} }
s32 CALLBACK DISCgetTOC(void* toc) static s32 DISCgetTOC(void* toc)
{ {
u8* tocBuff = static_cast<u8*>(toc); u8* tocBuff = static_cast<u8*>(toc);
if (curDiskType == CDVD_TYPE_NODISC) if (curDiskType == CDVD_TYPE_NODISC)
@ -478,39 +484,39 @@ s32 CALLBACK DISCgetTOC(void* toc)
return 0; return 0;
} }
s32 CALLBACK DISCgetDiskType() static s32 DISCgetDiskType()
{ {
return curDiskType; return curDiskType;
} }
s32 CALLBACK DISCgetTrayStatus() static s32 DISCgetTrayStatus()
{ {
return curTrayStatus; return curTrayStatus;
} }
s32 CALLBACK DISCctrlTrayOpen() static s32 DISCctrlTrayOpen()
{ {
curTrayStatus = CDVD_TRAY_OPEN; curTrayStatus = CDVD_TRAY_OPEN;
return 0; return 0;
} }
s32 CALLBACK DISCctrlTrayClose() static s32 DISCctrlTrayClose()
{ {
curTrayStatus = CDVD_TRAY_CLOSE; curTrayStatus = CDVD_TRAY_CLOSE;
return 0; return 0;
} }
void CALLBACK DISCnewDiskCB(void (*callback)()) static void DISCnewDiskCB(void (*callback)())
{ {
newDiscCB = 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); return cdvdDirectReadSector(lsn, mode, buffer);
} }
s32 CALLBACK DISCgetDualInfo(s32* dualType, u32* _layer1start) static s32 DISCgetDualInfo(s32* dualType, u32* _layer1start)
{ {
if (src == nullptr) if (src == nullptr)
return -1; return -1;
@ -532,7 +538,7 @@ s32 CALLBACK DISCgetDualInfo(s32* dualType, u32* _layer1start)
return -1; return -1;
} }
CDVD_API CDVDapi_Disc = const CDVD_API CDVDapi_Disc =
{ {
DISCclose, DISCclose,
DISCopen, DISCopen,

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -22,6 +22,8 @@
#include <mutex> #include <mutex>
#include <array> #include <array>
class Error;
struct track struct track
{ {
u32 start_lba; u32 start_lba;
@ -69,7 +71,7 @@ public:
IOCtlSrc(std::string filename); IOCtlSrc(std::string filename);
~IOCtlSrc(); ~IOCtlSrc();
bool Reopen(); bool Reopen(Error* error);
u32 GetSectorCount() const; u32 GetSectorCount() const;
const std::vector<toc_entry>& ReadTOC() const; const std::vector<toc_entry>& ReadTOC() const;
@ -96,6 +98,5 @@ void cdvdStopThread();
void cdvdRequestSector(u32 sector, s32 mode); void cdvdRequestSector(u32 sector, s32 mode);
u8* cdvdGetSector(u32 sector, s32 mode); u8* cdvdGetSector(u32 sector, s32 mode);
s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer); s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer);
s32 cdvdGetMediaType(); void cdvdRefreshData();
s32 cdvdRefreshData();
void cdvdParseTOC(); void cdvdParseTOC();

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -50,10 +50,10 @@ static std::atomic<bool> cdvd_is_open;
//bits: 12 would use 1<<12 entries, or 4096*16 sectors ~ 128MB //bits: 12 would use 1<<12 entries, or 4096*16 sectors ~ 128MB
#define CACHE_SIZE 12 #define CACHE_SIZE 12
const u32 CacheSize = 1U << CACHE_SIZE; static constexpr u32 CacheSize = 1U << CACHE_SIZE;
SectorInfo Cache[CacheSize]; static SectorInfo Cache[CacheSize];
u32 cdvdSectorHash(u32 lsn) static u32 cdvdSectorHash(u32 lsn)
{ {
u32 t = 0; u32 t = 0;
@ -70,7 +70,7 @@ u32 cdvdSectorHash(u32 lsn)
return t & m; return t & m;
} }
void cdvdCacheUpdate(u32 lsn, u8* data) static void cdvdCacheUpdate(u32 lsn, u8* data)
{ {
std::lock_guard<std::mutex> guard(s_cache_lock); std::lock_guard<std::mutex> guard(s_cache_lock);
u32 entry = cdvdSectorHash(lsn); u32 entry = cdvdSectorHash(lsn);
@ -79,7 +79,7 @@ void cdvdCacheUpdate(u32 lsn, u8* data)
Cache[entry].lsn = lsn; Cache[entry].lsn = lsn;
} }
bool cdvdCacheCheck(u32 lsn) static bool cdvdCacheCheck(u32 lsn)
{ {
std::lock_guard<std::mutex> guard(s_cache_lock); std::lock_guard<std::mutex> guard(s_cache_lock);
u32 entry = cdvdSectorHash(lsn); u32 entry = cdvdSectorHash(lsn);
@ -87,7 +87,7 @@ bool cdvdCacheCheck(u32 lsn)
return Cache[entry].lsn == lsn; return Cache[entry].lsn == lsn;
} }
bool cdvdCacheFetch(u32 lsn, u8* data) static bool cdvdCacheFetch(u32 lsn, u8* data)
{ {
std::lock_guard<std::mutex> guard(s_cache_lock); std::lock_guard<std::mutex> guard(s_cache_lock);
u32 entry = cdvdSectorHash(lsn); u32 entry = cdvdSectorHash(lsn);
@ -101,7 +101,7 @@ bool cdvdCacheFetch(u32 lsn, u8* data)
return false; return false;
} }
void cdvdCacheReset() static void cdvdCacheReset()
{ {
std::lock_guard<std::mutex> guard(s_cache_lock); std::lock_guard<std::mutex> guard(s_cache_lock);
for (u32 i = 0; i < CacheSize; i++) 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); u32 count = std::min(sectors_per_read, src->GetSectorCount() - sector);
const s32 media = src->GetMediaType(); const s32 media = src->GetMediaType();
@ -133,14 +133,14 @@ bool cdvdReadBlockOfSectors(u32 sector, u8* data)
return false; return false;
} }
void cdvdCallNewDiscCB() static void cdvdCallNewDiscCB()
{ {
weAreInNewDiskCB = true; weAreInNewDiskCB = true;
newDiscCB(); newDiscCB();
weAreInNewDiskCB = false; weAreInNewDiskCB = false;
} }
bool cdvdUpdateDiscStatus() static bool cdvdUpdateDiscStatus()
{ {
bool ready = src->DiscReady(); bool ready = src->DiscReady();
@ -175,7 +175,7 @@ bool cdvdUpdateDiscStatus()
return !ready; return !ready;
} }
void cdvdThread() static void cdvdThread()
{ {
u8 buffer[2352 * sectors_per_read]; u8 buffer[2352 * sectors_per_read];
u32 prefetches_left = 0; u32 prefetches_left = 0;
@ -379,12 +379,12 @@ s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer)
} }
} }
s32 cdvdGetMediaType() static s32 cdvdGetMediaType()
{ {
return src->GetMediaType(); return src->GetMediaType();
} }
s32 cdvdRefreshData() void cdvdRefreshData()
{ {
const char* diskTypeName = "Unknown"; const char* diskTypeName = "Unknown";
@ -428,6 +428,4 @@ s32 cdvdRefreshData()
printf(" * CDVD: Disk Type: %s\n", diskTypeName); printf(" * CDVD: Disk Type: %s\n", diskTypeName);
cdvdCacheReset(); cdvdCacheReset();
return 0;
} }

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -13,19 +13,13 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
/*
* Original code from libcdvd by Hiryu & Sjeep (C) 2002
* Modified by Florin for PCSX2 emu
* Fixed CdRead by linuzappz
*/
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "IsoFileFormats.h" #include "IsoFileFormats.h"
#include "AsyncFileReader.h" #include "AsyncFileReader.h"
#include "CDVD/CDVD.h" #include "CDVD/CDVD.h"
#include "common/Assertions.h" #include "common/Assertions.h"
#include "common/Error.h"
#include <cstring> #include <cstring>
#include <array> #include <array>
@ -37,23 +31,23 @@ static int pmode, cdtype;
static s32 layer1start = -1; static s32 layer1start = -1;
static bool layer1searched = false; static bool layer1searched = false;
void CALLBACK ISOclose() static void ISOclose()
{ {
iso.Close(); iso.Close();
} }
s32 CALLBACK ISOopen(const char* pTitle) static bool ISOopen(std::string filename, Error* error)
{ {
ISOclose(); // just in case ISOclose(); // just in case
if ((pTitle == NULL) || (pTitle[0] == 0)) if (filename.empty())
{ {
Console.Error("CDVDiso Error: No filename specified."); Error::SetString(error, "No filename specified.");
return -1; return false;
} }
if (!iso.Open(pTitle)) if (!iso.Open(std::move(filename), error, false))
return -1; return false;
switch (iso.GetType()) switch (iso.GetType())
{ {
@ -71,10 +65,10 @@ s32 CALLBACK ISOopen(const char* pTitle)
layer1start = -1; layer1start = -1;
layer1searched = false; layer1searched = false;
return 0; return true;
} }
s32 CALLBACK ISOreadSubQ(u32 lsn, cdvdSubQ* subq) static s32 ISOreadSubQ(u32 lsn, cdvdSubQ* subq)
{ {
// fake it // fake it
u8 min, sec, frm; u8 min, sec, frm;
@ -98,7 +92,7 @@ s32 CALLBACK ISOreadSubQ(u32 lsn, cdvdSubQ* subq)
return 0; return 0;
} }
s32 CALLBACK ISOgetTN(cdvdTN* Buffer) static s32 ISOgetTN(cdvdTN* Buffer)
{ {
Buffer->strack = 1; Buffer->strack = 1;
Buffer->etrack = 1; Buffer->etrack = 1;
@ -106,7 +100,7 @@ s32 CALLBACK ISOgetTN(cdvdTN* Buffer)
return 0; return 0;
} }
s32 CALLBACK ISOgetTD(u8 Track, cdvdTD* Buffer) static s32 ISOgetTD(u8 Track, cdvdTD* Buffer)
{ {
if (Track == 0) if (Track == 0)
{ {
@ -170,7 +164,7 @@ static void FindLayer1Start()
} }
// Should return 0 if no error occurred, or -1 if layer detection FAILED. // 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(); FindLayer1Start();
@ -187,12 +181,12 @@ s32 CALLBACK ISOgetDualInfo(s32* dualType, u32* _layer1start)
return 0; return 0;
} }
s32 CALLBACK ISOgetDiskType() static s32 ISOgetDiskType()
{ {
return cdtype; return cdtype;
} }
s32 CALLBACK ISOgetTOC(void* toc) static s32 ISOgetTOC(void* toc)
{ {
u8 type = ISOgetDiskType(); u8 type = ISOgetDiskType();
u8* tocBuff = (u8*)toc; u8* tocBuff = (u8*)toc;
@ -326,7 +320,7 @@ s32 CALLBACK ISOgetTOC(void* toc)
return 0; 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}; static u8 cdbuffer[CD_FRAMESIZE_RAW] = {0};
@ -377,7 +371,7 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
return 0; return 0;
} }
s32 CALLBACK ISOreadTrack(u32 lsn, int mode) static s32 ISOreadTrack(u32 lsn, int mode)
{ {
int _lsn = lsn; int _lsn = lsn;
@ -391,41 +385,41 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
return 0; return 0;
} }
s32 CALLBACK ISOgetBuffer(u8* buffer) static s32 ISOgetBuffer(u8* buffer)
{ {
return iso.FinishRead3(buffer, pmode); return iso.FinishRead3(buffer, pmode);
} }
//u8* CALLBACK ISOgetBuffer() //static u8* ISOgetBuffer()
//{ //{
// iso.FinishRead(); // iso.FinishRead();
// return pbuffer; // return pbuffer;
//} //}
s32 CALLBACK ISOgetTrayStatus() static s32 ISOgetTrayStatus()
{ {
return CDVD_TRAY_CLOSE; return CDVD_TRAY_CLOSE;
} }
s32 CALLBACK ISOctrlTrayOpen() static s32 ISOctrlTrayOpen()
{ {
return 0; return 0;
} }
s32 CALLBACK ISOctrlTrayClose() static s32 ISOctrlTrayClose()
{ {
return 0; return 0;
} }
s32 CALLBACK ISOdummyS32() static s32 ISOdummyS32()
{ {
return 0; return 0;
} }
void CALLBACK ISOnewDiskCB(void (*/* callback */)()) static void ISOnewDiskCB(void (* /* callback */)())
{ {
} }
CDVD_API CDVDapi_Iso = const CDVD_API CDVDapi_Iso =
{ {
ISOclose, ISOclose,
@ -440,7 +434,6 @@ CDVD_API CDVDapi_Iso =
ISOdummyS32, // trayStatus ISOdummyS32, // trayStatus
ISOdummyS32, // trayOpen ISOdummyS32, // trayOpen
ISOdummyS32, // trayClose ISOdummyS32, // trayClose
ISOnewDiskCB, ISOnewDiskCB,
ISOreadSector, ISOreadSector,

View File

@ -176,27 +176,19 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt
return chd; return chd;
} }
bool ChdFileReader::Open2(std::string fileName) bool ChdFileReader::Open2(std::string filename, Error* error)
{ {
Close2(); 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) if (!fp)
{
Console.Error(fmt::format("Failed to open CHD '{}': errno {}", m_filename, errno));
return false; return false;
}
// TODO: Propagate error back to caller. ChdFile = OpenCHD(m_filename, std::move(fp), error, 0);
Error error;
ChdFile = OpenCHD(m_filename, std::move(fp), &error, 0);
if (!ChdFile) if (!ChdFile)
{
Console.Error(fmt::format("Failed to open CHD '{}': {}", m_filename, error.GetDescription()));
return false; return false;
}
const chd_header* chd_header = chd_get_header(ChdFile); const chd_header* chd_header = chd_get_header(ChdFile);
hunk_size = chd_header->hunkbytes; hunk_size = chd_header->hunkbytes;

View File

@ -19,17 +19,17 @@
typedef struct _chd_file chd_file; typedef struct _chd_file chd_file;
class ChdFileReader : public ThreadedFileReader class ChdFileReader final : public ThreadedFileReader
{ {
DeclareNoncopyableObject(ChdFileReader); DeclareNoncopyableObject(ChdFileReader);
public: public:
ChdFileReader(); ChdFileReader();
virtual ~ChdFileReader() override; ~ChdFileReader() override;
static bool CanHandle(const std::string& fileName, const std::string& displayName); 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; Chunk ChunkForOffset(u64 offset) override;
int ReadChunk(void* dst, s64 blockID) override; int ReadChunk(void* dst, s64 blockID) override;

View File

@ -1,29 +1,31 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * 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. * 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; * 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 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details. * 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. * You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "AsyncFileReader.h" #include "AsyncFileReader.h"
#include "CsoFileReader.h" #include "CsoFileReader.h"
#include "common/Pcsx2Types.h"
#include "common/FileSystem.h" #include "common/FileSystem.h"
#include "common/Error.h"
#include "common/StringUtil.h" #include "common/StringUtil.h"
#include <zlib.h> #include <zlib.h>
static constexpr u32 CSO_CHUNKCACHE_SIZE_MB = 200;
// Implementation of CSO compressed ISO reading, based on: // Implementation of CSO compressed ISO reading, based on:
// https://github.com/unknownbrackets/maxcso/blob/master/README_CSO.md // https://github.com/unknownbrackets/maxcso/blob/master/README_CSO.md
struct CsoHeader struct CsoHeader
@ -39,6 +41,16 @@ struct CsoHeader
static const u32 CSO_READ_BUFFER_SIZE = 256 * 1024; 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 CsoFileReader::CanHandle(const std::string& fileName, const std::string& displayName)
{ {
bool supported = false; 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)) if (fread(&hdr, 1, sizeof(hdr), fp) == sizeof(hdr))
{ {
supported = ValidateHeader(hdr); supported = ValidateHeader(hdr, nullptr);
} }
fclose(fp); fclose(fp);
} }
@ -58,26 +70,27 @@ bool CsoFileReader::CanHandle(const std::string& fileName, const std::string& di
return supported; 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') if (hdr.magic[0] != 'C' || hdr.magic[1] != 'I' || hdr.magic[2] != 'S' || hdr.magic[3] != 'O')
{ {
// Invalid magic, definitely a bad file. // Invalid magic, definitely a bad file.
Error::SetString(error, "File is not a CHD.");
return false; return false;
} }
if (hdr.ver > 1) if (hdr.ver > 1)
{ {
Console.Error("Only CSOv1 files are supported."); Error::SetString(error, "Only CSOv1 files are supported.");
return false; return false;
} }
if ((hdr.frame_size & (hdr.frame_size - 1)) != 0) 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; return false;
} }
if (hdr.frame_size < 2048) 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; return false;
} }
@ -85,14 +98,14 @@ bool CsoFileReader::ValidateHeader(const CsoHeader& hdr)
return true; return true;
} }
bool CsoFileReader::Open2(std::string fileName) bool CsoFileReader::Open2(std::string filename, Error* error)
{ {
Close2(); Close2();
m_filename = std::move(fileName); m_filename = std::move(filename);
m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb"); m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb", error);
bool success = false; bool success = false;
if (m_src && ReadFileHeader() && InitializeBuffers()) if (m_src && ReadFileHeader(error) && InitializeBuffers(error))
{ {
success = true; success = true;
} }
@ -105,21 +118,18 @@ bool CsoFileReader::Open2(std::string fileName)
return true; 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)) 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; return false;
} }
if (!ValidateHeader(hdr)) if (!ValidateHeader(hdr, error))
{
Console.Error("CSO has invalid header.");
return false; return false;
}
m_frameSize = hdr.frame_size; m_frameSize = hdr.frame_size;
// Determine the translation from bytes to frame. // Determine the translation from bytes to frame.
@ -136,7 +146,7 @@ bool CsoFileReader::ReadFileHeader()
return true; return true;
} }
bool CsoFileReader::InitializeBuffers() bool CsoFileReader::InitializeBuffers(Error* error)
{ {
// Round up, since part of a frame requires a full frame. // Round up, since part of a frame requires a full frame.
u32 numFrames = (u32)((m_totalSize + m_frameSize - 1) / m_frameSize); 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. // We might read a bit of alignment too, so be prepared.
if (m_frameSize + (1 << m_indexShift) < CSO_READ_BUFFER_SIZE) if (m_frameSize + (1 << m_indexShift) < CSO_READ_BUFFER_SIZE)
{ {
m_readBuffer = new u8[CSO_READ_BUFFER_SIZE]; m_readBuffer = std::make_unique<u8[]>(CSO_READ_BUFFER_SIZE);
} }
else else
{ {
m_readBuffer = new u8[m_frameSize + (1 << m_indexShift)]; m_readBuffer = std::make_unique<u8[]>(m_frameSize + (1 << m_indexShift));
} }
const u32 indexSize = numFrames + 1; const u32 indexSize = numFrames + 1;
m_index = new u32[indexSize]; m_index = std::make_unique<u32[]>(indexSize);
if (fread(m_index, sizeof(u32), indexSize, m_src) != 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; return false;
} }
m_z_stream = new z_stream; m_z_stream = std::make_unique<z_stream>();
m_z_stream->zalloc = Z_NULL; m_z_stream->zalloc = Z_NULL;
m_z_stream->zfree = Z_NULL; m_z_stream->zfree = Z_NULL;
m_z_stream->opaque = 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; return false;
} }
@ -179,24 +189,21 @@ void CsoFileReader::Close2()
if (m_src) if (m_src)
{ {
fclose(m_src); fclose(m_src);
m_src = NULL; m_src = nullptr;
} }
if (m_z_stream) if (m_z_stream)
{ {
inflateEnd(m_z_stream); inflateEnd(m_z_stream.get());
m_z_stream = NULL; m_z_stream.reset();
} }
if (m_readBuffer) m_readBuffer.reset();
{ m_index.reset();
delete[] m_readBuffer; }
m_readBuffer = NULL;
} u32 CsoFileReader::GetBlockCount() const
if (m_index) {
{ return static_cast<u32>((m_totalSize - m_dataoffset) / m_blocksize);
delete[] m_index;
m_index = NULL;
}
} }
ThreadedFileReader::Chunk CsoFileReader::ChunkForOffset(u64 offset) ThreadedFileReader::Chunk CsoFileReader::ChunkForOffset(u64 offset)
@ -215,7 +222,7 @@ ThreadedFileReader::Chunk CsoFileReader::ChunkForOffset(u64 offset)
return chunk; return chunk;
} }
int CsoFileReader::ReadChunk(void *dst, s64 chunkID) int CsoFileReader::ReadChunk(void* dst, s64 chunkID)
{ {
if (chunkID < 0) if (chunkID < 0)
return -1; 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 might be less bytes than frameRawSize in case of padding on the last frame.
// This is because the index positions must be aligned. // 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->avail_in = readRawBytes;
m_z_stream->next_out = static_cast<Bytef*>(dst); m_z_stream->next_out = static_cast<Bytef*>(dst);
m_z_stream->avail_out = m_frameSize; 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; bool success = status == Z_STREAM_END && m_z_stream->total_out == m_frameSize;
if (!success) if (!success)
Console.Error("Unable to decompress CSO frame using zlib."); Console.Error("Unable to decompress CSO frame using zlib.");
inflateReset(m_z_stream); inflateReset(m_z_stream.get());
return success ? m_frameSize : 0; return success ? m_frameSize : 0;
} }

View File

@ -1,17 +1,17 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * 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. * 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; * 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 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details. * 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. * You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
@ -31,56 +31,40 @@
struct CsoHeader; struct CsoHeader;
typedef struct z_stream_s z_stream; typedef struct z_stream_s z_stream;
static const uint CSO_CHUNKCACHE_SIZE_MB = 200; class CsoFileReader final : public ThreadedFileReader
class CsoFileReader : public ThreadedFileReader
{ {
DeclareNoncopyableObject(CsoFileReader); DeclareNoncopyableObject(CsoFileReader);
public: public:
CsoFileReader(void) CsoFileReader();
: m_frameSize(0) ~CsoFileReader() override;
, 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(); };
static bool CanHandle(const std::string& fileName, const std::string& displayName); 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; 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 u32 GetBlockCount() const override;
{
return (m_totalSize - m_dataoffset) / m_blocksize;
};
private: private:
static bool ValidateHeader(const CsoHeader& hdr); static bool ValidateHeader(const CsoHeader& hdr, Error* error);
bool ReadFileHeader(); bool ReadFileHeader(Error* error);
bool InitializeBuffers(); bool InitializeBuffers(Error* error);
int ReadFromFrame(u8* dest, u64 pos, int maxBytes); int ReadFromFrame(u8* dest, u64 pos, int maxBytes);
bool DecompressFrame(Bytef* dst, u32 frame, u32 readBufferSize); bool DecompressFrame(Bytef* dst, u32 frame, u32 readBufferSize);
bool DecompressFrame(u32 frame, u32 readBufferSize); bool DecompressFrame(u32 frame, u32 readBufferSize);
u32 m_frameSize; u32 m_frameSize = 0;
u8 m_frameShift; u8 m_frameShift = 0;
u8 m_indexShift; u8 m_indexShift = 0;
u8* m_readBuffer;; std::unique_ptr<u8[]> m_readBuffer;
u32* m_index;
u64 m_totalSize; std::unique_ptr<u32[]> m_index;
u64 m_totalSize = 0;
// The actual source cso file handle. // The actual source cso file handle.
FILE* m_src; std::FILE* m_src = nullptr;
z_stream* m_z_stream; std::unique_ptr<z_stream> m_z_stream;
}; };

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -17,6 +17,8 @@
#include "CDVD/CDVDdiscReader.h" #include "CDVD/CDVDdiscReader.h"
#include "CDVD/CDVD.h" #include "CDVD/CDVD.h"
#include "common/Error.h"
#ifdef __APPLE__ #ifdef __APPLE__
#include <IOKit/storage/IOCDMediaBSDClient.h> #include <IOKit/storage/IOCDMediaBSDClient.h>
#include <IOKit/storage/IODVDMediaBSDClient.h> #include <IOKit/storage/IODVDMediaBSDClient.h>
@ -43,7 +45,7 @@ IOCtlSrc::~IOCtlSrc()
} }
} }
bool IOCtlSrc::Reopen() bool IOCtlSrc::Reopen(Error* error)
{ {
if (m_device != -1) if (m_device != -1)
close(m_device); close(m_device);
@ -52,7 +54,10 @@ bool IOCtlSrc::Reopen()
// drive is empty. Probably does other things too. // drive is empty. Probably does other things too.
m_device = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK); m_device = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK);
if (m_device == -1) if (m_device == -1)
{
Error::SetErrno(error, errno);
return false; return false;
}
// DVD detection MUST be first on Linux - The TOC ioctls work for both // DVD detection MUST be first on Linux - The TOC ioctls work for both
// CDs and DVDs. // CDs and DVDs.
@ -256,7 +261,7 @@ bool IOCtlSrc::DiscReady()
if (!m_sectors) if (!m_sectors)
{ {
Reopen(); Reopen(nullptr);
} }
return !!m_sectors; return !!m_sectors;

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -22,12 +22,12 @@
#include "CDVD/zlib_indexed.h" #include "CDVD/zlib_indexed.h"
#include "common/FileSystem.h" #include "common/FileSystem.h"
#include "common/Error.h"
#include "common/Path.h" #include "common/Path.h"
#include "common/StringUtil.h" #include "common/StringUtil.h"
#include "common/Timer.h"
#include <fstream> #include "fmt/format.h"
#define CLAMP(val, minval, maxval) (std::min(maxval, std::max(minval, val)))
#define GZIP_ID "PCSX2.index.gzip.v1|" #define GZIP_ID "PCSX2.index.gzip.v1|"
#define GZIP_ID_LEN (sizeof(GZIP_ID) - 1) /* sizeof includes the \0 terminator */ #define GZIP_ID_LEN (sizeof(GZIP_ID) - 1) /* sizeof includes the \0 terminator */
@ -39,40 +39,43 @@
static Access* ReadIndexFromFile(const char* filename) static Access* ReadIndexFromFile(const char* filename)
{ {
auto fp = FileSystem::OpenManagedCFile(filename, "rb"); auto fp = FileSystem::OpenManagedCFile(filename, "rb");
if (!fp)
return nullptr;
s64 size; 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); Console.Error(fmt::format("Invalid gzip index size: {}", size));
return 0; return nullptr;
} }
char fileId[GZIP_ID_LEN + 1] = {0}; 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) 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); Console.Error(fmt::format("Incompatible gzip index, please delete it manually: '{}'", filename));
return 0; return nullptr;
} }
Access* const index = (Access*)malloc(sizeof(Access)); Access* const index = static_cast<Access*>(std::malloc(sizeof(Access)));
const s64 datasize = size - GZIP_ID_LEN - sizeof(Access); const s64 datasize = size - GZIP_ID_LEN - sizeof(Access);
if (std::fread(index, sizeof(Access), 1, fp.get()) != 1 || if (std::fread(index, sizeof(Access), 1, fp.get()) != 1 ||
datasize != static_cast<s64>(index->have) * static_cast<s64>(sizeof(Point))) datasize != static_cast<s64>(index->have) * static_cast<s64>(sizeof(Point)))
{ {
Console.Error("Error: Unexpected size of gzip index, please delete it manually: '%s'.", filename); Console.Error(fmt::format("Unexpected size of gzip index, please delete it manually: '{}'.", filename));
free(index); std::free(index);
return 0; return 0;
} }
char* buffer = (char*)malloc(datasize); char* buffer = static_cast<char*>(std::malloc(datasize));
if (std::fread(buffer, datasize, 1, fp.get()) != 1) if (std::fread(buffer, datasize, 1, fp.get()) != 1)
{ {
Console.Error("Error: failed read of gzip index, please delete it manually: '%s'.", filename); Console.Error(fmt::format("Failed read of gzip index, please delete it manually: '{}'.", filename));
free(buffer); std::free(buffer);
free(index); std::free(index);
return 0; return 0;
} }
index->list = (Point*)buffer; // adjust list pointer index->list = reinterpret_cast<Point*>(buffer); // adjust list pointer
return index; 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. // 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. // 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, static std::string ApplyTemplate(const std::string& name, const std::string& base,
const std::string& fileTemplate, const std::string& filename, const std::string& fileTemplate, const std::string& filename,
bool canEndWithKey) bool canEndWithKey, Error* error)
{ {
// both sides // both sides
std::string trimmedTemplate(StringUtil::StripWhitespace(fileTemplate)); std::string trimmedTemplate(StringUtil::StripWhitespace(fileTemplate));
std::string::size_type first = trimmedTemplate.find(INDEX_TEMPLATE_KEY); 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 || first != trimmedTemplate.rfind(INDEX_TEMPLATE_KEY) // more than one instance
|| (!canEndWithKey && first == trimmedTemplate.length() - std::strlen(INDEX_TEMPLATE_KEY))) || (!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.", "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 {}; return {};
} }
@ -148,23 +151,23 @@ static std::string ApplyTemplate(const std::string& name, const std::string& bas
return trimmedTemplate; 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; 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()
GzippedFileReader::GzippedFileReader(void) : m_cache(GZFILE_CACHE_SIZE_MB)
: mBytesRead(0)
, m_pIndex(0)
, m_zstates(0)
, m_src(0)
, m_cache(GZFILE_CACHE_SIZE_MB)
{ {
m_blocksize = 2048; m_blocksize = 2048;
AsyncPrefetchReset(); AsyncPrefetchReset();
}; }
GzippedFileReader::~GzippedFileReader()
{
Close();
}
void GzippedFileReader::InitZstates() void GzippedFileReader::InitZstates()
{ {
@ -268,15 +271,18 @@ bool GzippedFileReader::CanHandle(const std::string& fileName, const std::string
return StringUtil::EndsWith(fileName, ".gz"); return StringUtil::EndsWith(fileName, ".gz");
} }
bool GzippedFileReader::OkIndex() bool GzippedFileReader::OkIndex(Error* error)
{ {
if (m_pIndex) if (m_pIndex)
return true; return true;
// Try to read index from disk // Try to read index from disk
const std::string indexfile(iso2indexname(m_filename)); const std::string indexfile(iso2indexname(m_filename, error));
if (indexfile.empty()) 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()))) 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) 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.", 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("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)"); Console.Warning("(smaller intervals mean bigger index file and quicker but more frequent decompressions)");
} }
@ -308,7 +314,7 @@ bool GzippedFileReader::OkIndex()
} }
else 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); free_index(index);
InitZstates(); InitZstates();
return false; return false;
@ -318,15 +324,15 @@ bool GzippedFileReader::OkIndex()
return true; return true;
} }
bool GzippedFileReader::Open(std::string fileName) bool GzippedFileReader::Open(std::string filename, Error* error)
{ {
Close(); Close();
m_filename = std::move(fileName); m_filename = std::move(filename);
if (!(m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb")) || !OkIndex()) if (!(m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb", error)) || !OkIndex(error))
{ {
Close(); Close();
return false; return false;
}; }
AsyncPrefetchOpen(); AsyncPrefetchOpen();
return true; return true;
@ -336,18 +342,18 @@ void GzippedFileReader::BeginRead(void* pBuffer, uint sector, uint count)
{ {
// No a-sync support yet, implement as sync // No a-sync support yet, implement as sync
mBytesRead = ReadSync(pBuffer, sector, count); mBytesRead = ReadSync(pBuffer, sector, count);
return; }
};
int GzippedFileReader::FinishRead(void) int GzippedFileReader::FinishRead()
{ {
int res = mBytesRead; int res = mBytesRead;
mBytesRead = -1; mBytesRead = -1;
return res; return res;
}; }
#define PTT clock_t void GzippedFileReader::CancelRead()
#define NOW() (clock() / (CLOCKS_PER_SEC / 1000)) {
}
int GzippedFileReader::ReadSync(void* pBuffer, uint sector, uint count) 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) int GzippedFileReader::_ReadSync(void* pBuffer, s64 offset, uint bytesToRead)
{ {
if (!OkIndex()) if (!OkIndex(nullptr))
return -1; return -1;
// Without all the caching, chunking and states, this would be enough: // 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 // Not available from cache. Decompress from optimal starting
// point in GZFILE_READ_CHUNK_SIZE chunks and cache each chunk. // 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 s64 extractOffset = GetOptimalExtractionStart(offset); // guaranteed in GZFILE_READ_CHUNK_SIZE boundaries
int size = offset + maxInChunk - extractOffset; int size = offset + maxInChunk - extractOffset;
unsigned char* extracted = (unsigned char*)malloc(size); unsigned char* extracted = (unsigned char*)malloc(size);
@ -446,7 +452,7 @@ int GzippedFileReader::_ReadSync(void* pBuffer, s64 offset, uint bytesToRead)
{ // split into cacheable chunks { // split into cacheable chunks
for (int i = 0; i < size; i += GZFILE_READ_CHUNK_SIZE) 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; void* chunk = available ? malloc(available) : 0;
if (available) if (available)
memcpy(chunk, extracted + i, available); memcpy(chunk, extracted + i, available);
@ -455,13 +461,14 @@ int GzippedFileReader::_ReadSync(void* pBuffer, s64 offset, uint bytesToRead)
free(extracted); free(extracted);
} }
int duration = NOW() - s; if (const double duration = start_time.GetTimeMilliseconds(); duration > 10)
if (duration > 10) {
Console.WriteLn(Color_Gray, "gunzip: chunk #%5d-%2d : %1.2f MB - %d ms", Console.WriteLn(Color_Gray, "gunzip: chunk #%5d-%2d : %1.2f MB - %d ms",
(int)(offset / 4 / 1024 / 1024), (int)(offset / 4 / 1024 / 1024),
(int)(offset % (4 * 1024 * 1024) / GZFILE_READ_CHUNK_SIZE), (int)(offset % (4 * 1024 * 1024) / GZFILE_READ_CHUNK_SIZE),
(float)size / 1024 / 1024, (float)size / 1024 / 1024,
duration); duration);
}
return copied; return copied;
} }
@ -481,8 +488,25 @@ void GzippedFileReader::Close()
if (m_src) if (m_src)
{ {
fclose(m_src); fclose(m_src);
m_src = 0; m_src = nullptr;
} }
AsyncPrefetchClose(); 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;
}

View File

@ -1,59 +1,53 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * 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. * 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; * 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 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details. * 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. * You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
typedef struct zstate Zstate;
#include "AsyncFileReader.h" #include "AsyncFileReader.h"
#include "ChunksCache.h" #include "ChunksCache.h"
#include "zlib_indexed.h" #include "zlib_indexed.h"
#define GZFILE_SPAN_DEFAULT (1048576L * 4) /* distance between direct access points when creating a new index */ static constexpr int GZFILE_SPAN_DEFAULT = (1048576 * 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) */ static constexpr int 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_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); DeclareNoncopyableObject(GzippedFileReader);
public: public:
GzippedFileReader(void); GzippedFileReader();
~GzippedFileReader();;
virtual ~GzippedFileReader(void) { Close(); };
static bool CanHandle(const std::string& fileName, const std::string& displayName); 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); void BeginRead(void* pBuffer, u32 sector, u32 count);
virtual int FinishRead(void); int FinishRead();
virtual void CancelRead(void){}; void CancelRead();
virtual void Close(void); void Close() override;
virtual uint GetBlockCount(void) const u32 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);
};
virtual void SetBlockSize(uint bytes) { m_blocksize = bytes; } void SetBlockSize(u32 bytes) override;
virtual void SetDataOffset(int bytes) { m_dataoffset = bytes; } void SetDataOffset(u32 bytes) override;
private: private:
class Czstate class Czstate
@ -70,23 +64,23 @@ private:
Zstate state; 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); s64 GetOptimalExtractionStart(s64 offset);
int _ReadSync(void* pBuffer, s64 offset, uint bytesToRead); int _ReadSync(void* pBuffer, s64 offset, uint bytesToRead);
void InitZstates(); void InitZstates();
int mBytesRead; // Temp sync read result when simulating async read int mBytesRead = 0; // Temp sync read result when simulating async read
Access* m_pIndex; // Quick access index Access* m_pIndex = nullptr; // Quick access index
Czstate* m_zstates; Czstate* m_zstates = nullptr;
FILE* m_src; FILE* m_src = nullptr;
ChunksCache m_cache; ChunksCache m_cache;
#ifdef _WIN32 #ifdef _WIN32
// Used by async prefetch // Used by async prefetch
HANDLE hOverlappedFile; HANDLE hOverlappedFile = INVALID_HANDLE_VALUE;
OVERLAPPED asyncOperationContext; OVERLAPPED asyncOperationContext = {};
bool asyncInProgress; bool asyncInProgress = false;
char mDummyAsyncPrefetchTarget[GZFILE_READ_CHUNK_SIZE]; char mDummyAsyncPrefetchTarget[GZFILE_READ_CHUNK_SIZE];
#endif #endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -21,6 +21,7 @@
#include "Host.h" #include "Host.h"
#include "common/Assertions.h" #include "common/Assertions.h"
#include "common/Error.h"
#include "fmt/format.h" #include "fmt/format.h"
@ -198,10 +199,10 @@ void InputIsoFile::_init()
bool InputIsoFile::Test(std::string srcfile) bool InputIsoFile::Test(std::string srcfile)
{ {
Close(); 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(); Close();
m_filename = std::move(srcfile); m_filename = std::move(srcfile);
@ -222,7 +223,7 @@ bool InputIsoFile::Open(std::string srcfile, bool testOnly)
m_reader = new FlatFileReader(EmuConfig.CdvdShareWrite); m_reader = new FlatFileReader(EmuConfig.CdvdShareWrite);
} }
if (!m_reader->Open(m_filename)) if (!m_reader->Open(m_filename, error))
return false; return false;
// It might actually be a blockdump file. // It might actually be a blockdump file.
@ -233,7 +234,7 @@ bool InputIsoFile::Open(std::string srcfile, bool testOnly)
delete m_reader; delete m_reader;
BlockdumpFileReader* bdr = new BlockdumpFileReader(); BlockdumpFileReader* bdr = new BlockdumpFileReader();
bdr->Open(m_filename); bdr->Open(m_filename, error);
m_blockofs = bdr->GetBlockOffset(); m_blockofs = bdr->GetBlockOffset();
m_blocksize = bdr->GetBlockSize(); m_blocksize = bdr->GetBlockSize();
@ -253,7 +254,7 @@ bool InputIsoFile::Open(std::string srcfile, bool testOnly)
if (!detected) 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(); Close();
return false; return false;
} }

View File

@ -21,6 +21,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
class Error;
enum isoType enum isoType
{ {
ISOTYPE_ILLEGAL = 0, ISOTYPE_ILLEGAL = 0,
@ -35,7 +37,7 @@ static const int CD_FRAMESIZE_RAW = 2448;
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// isoFile // isoFile
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
class InputIsoFile class InputIsoFile final
{ {
DeclareNoncopyableObject(InputIsoFile); DeclareNoncopyableObject(InputIsoFile);
@ -67,7 +69,7 @@ protected:
public: public:
InputIsoFile(); InputIsoFile();
virtual ~InputIsoFile(); ~InputIsoFile();
bool IsOpened() const; bool IsOpened() const;
@ -81,7 +83,7 @@ public:
} }
bool Test(std::string srcfile); bool Test(std::string srcfile);
bool Open(std::string srcfile, bool testOnly = false); bool Open(std::string srcfile, Error* error, bool testOnly);
void Close(); void Close();
bool Detect(bool readType = true); bool Detect(bool readType = true);
@ -97,7 +99,7 @@ protected:
void FindParts(); void FindParts();
}; };
class OutputIsoFile class OutputIsoFile final
{ {
DeclareNoncopyableObject(OutputIsoFile); DeclareNoncopyableObject(OutputIsoFile);
@ -120,7 +122,7 @@ protected:
public: public:
OutputIsoFile(); OutputIsoFile();
virtual ~OutputIsoFile(); ~OutputIsoFile();
bool IsOpened() const; bool IsOpened() const;
u32 GetBlockSize() const; u32 GetBlockSize() const;

View File

@ -56,12 +56,9 @@ bool IsoHasher::Open(std::string iso_path, Error* error)
CDVDsys_SetFile(CDVD_SourceType::Iso, std::move(iso_path)); CDVDsys_SetFile(CDVD_SourceType::Iso, std::move(iso_path));
CDVDsys_ChangeSource(CDVD_SourceType::Iso); CDVDsys_ChangeSource(CDVD_SourceType::Iso);
m_is_open = DoCDVDopen(); m_is_open = DoCDVDopen(error);
if (!m_is_open) if (!m_is_open)
{
Error::SetString(error, "Failed to open CDVD.");
return false; return false;
}
const s32 type = DoCDVDdetectDiskType(); const s32 type = DoCDVDdetectDiskType();
switch (type) switch (type)

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -17,6 +17,8 @@
#include "CDVD/CDVDdiscReader.h" #include "CDVD/CDVDdiscReader.h"
#include "CDVD/CDVD.h" #include "CDVD/CDVD.h"
#include "common/Error.h"
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -40,7 +42,7 @@ IOCtlSrc::~IOCtlSrc()
} }
} }
bool IOCtlSrc::Reopen() bool IOCtlSrc::Reopen(Error* error)
{ {
if (m_device != -1) if (m_device != -1)
close(m_device); close(m_device);
@ -49,7 +51,10 @@ bool IOCtlSrc::Reopen()
// drive is empty. Probably does other things too. // drive is empty. Probably does other things too.
m_device = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK); m_device = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK);
if (m_device == -1) if (m_device == -1)
{
Error::SetErrno(error, errno);
return false; return false;
}
// DVD detection MUST be first on Linux - The TOC ioctls work for both // DVD detection MUST be first on Linux - The TOC ioctls work for both
// CDs and DVDs. // CDs and DVDs.
@ -211,7 +216,7 @@ bool IOCtlSrc::DiscReady()
if (ioctl(m_device, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK) if (ioctl(m_device, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK)
{ {
if (!m_sectors) if (!m_sectors)
Reopen(); Reopen(nullptr);
} }
else else
{ {

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * 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; return allDone;
} }
bool ThreadedFileReader::Open(std::string fileName) bool ThreadedFileReader::Open(std::string filename, Error* error)
{ {
CancelAndWaitUntilStopped(); 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(); u32 blocksize = InternalBlockSize();
u64 offset = (u64)sector * (u64)blocksize + m_dataoffset; u64 offset = (u64)sector * (u64)blocksize + m_dataoffset;
@ -316,7 +316,7 @@ void ThreadedFileReader::CancelAndWaitUntilStopped(void)
m_condition.wait(lock); 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(); s32 blocksize = InternalBlockSize();
u64 offset = (u64)sector * (u64)blocksize + m_dataoffset; u64 offset = (u64)sector * (u64)blocksize + m_dataoffset;
@ -371,12 +371,12 @@ void ThreadedFileReader::Close(void)
Close2(); Close2();
} }
void ThreadedFileReader::SetBlockSize(uint bytes) void ThreadedFileReader::SetBlockSize(u32 bytes)
{ {
m_blocksize = bytes; m_blocksize = bytes;
} }
void ThreadedFileReader::SetDataOffset(int bytes) void ThreadedFileReader::SetDataOffset(u32 bytes)
{ {
m_dataoffset = bytes; m_dataoffset = bytes;
} }

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * 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` /// Synchronously read the given block into `dst`
virtual int ReadChunk(void* dst, s64 chunkID) = 0; virtual int ReadChunk(void* dst, s64 chunkID) = 0;
/// AsyncFileReader open but ThreadedFileReader needs prep work first /// 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 /// AsyncFileReader close but ThreadedFileReader needs prep work first
virtual void Close2(void) = 0; virtual void Close2() = 0;
ThreadedFileReader(); ThreadedFileReader();
~ThreadedFileReader(); ~ThreadedFileReader();
@ -108,12 +108,12 @@ private:
bool TryCachedRead(void*& buffer, u64& offset, u32& size, const std::lock_guard<std::mutex>&); bool TryCachedRead(void*& buffer, u64& offset, u32& size, const std::lock_guard<std::mutex>&);
public: public:
bool Open(std::string fileName) final override; bool Open(std::string filename, Error* error) final override;
int ReadSync(void* pBuffer, uint sector, uint count) final override; int ReadSync(void* pBuffer, u32 sector, u32 count) final override;
void BeginRead(void* pBuffer, uint sector, uint count) final override; void BeginRead(void* pBuffer, u32 sector, u32 count) final override;
int FinishRead(void) final override; int FinishRead() final override;
void CancelRead(void) final override; void CancelRead() final override;
void Close(void) final override; void Close() final override;
void SetBlockSize(uint bytes) final override; void SetBlockSize(u32 bytes) final override;
void SetDataOffset(int bytes) final override; void SetDataOffset(u32 bytes) final override;
}; };

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -16,7 +16,9 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "CDVD/CDVDdiscReader.h" #include "CDVD/CDVDdiscReader.h"
#include "CDVD/CDVD.h" #include "CDVD/CDVD.h"
#include "common/Console.h" #include "common/Console.h"
#include "common/Error.h"
#include <winioctl.h> #include <winioctl.h>
#include <ntddcdvd.h> #include <ntddcdvd.h>
@ -49,7 +51,7 @@ IOCtlSrc::~IOCtlSrc()
// If a new disc is inserted, ReadFile will fail unless the device is closed // If a new disc is inserted, ReadFile will fail unless the device is closed
// and reopened. // and reopened.
bool IOCtlSrc::Reopen() bool IOCtlSrc::Reopen(Error* error)
{ {
if (m_device != INVALID_HANDLE_VALUE) if (m_device != INVALID_HANDLE_VALUE)
CloseHandle(m_device); CloseHandle(m_device);
@ -59,7 +61,10 @@ bool IOCtlSrc::Reopen()
FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, nullptr); FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
if (m_device == INVALID_HANDLE_VALUE) if (m_device == INVALID_HANDLE_VALUE)
{
Error::SetWin32(error, GetLastError());
return false; return false;
}
DWORD unused; DWORD unused;
// Required to read from layer 1 of Dual layer DVDs // Required to read from layer 1 of Dual layer DVDs
@ -321,7 +326,7 @@ bool IOCtlSrc::DiscReady()
nullptr, 0, &unused, nullptr)) nullptr, 0, &unused, nullptr))
{ {
if (!m_sectors) if (!m_sectors)
Reopen(); Reopen(nullptr);
} }
else else
{ {

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -15,7 +15,9 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "AsyncFileReader.h" #include "AsyncFileReader.h"
#include "common/FileSystem.h" #include "common/FileSystem.h"
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
@ -27,34 +29,35 @@
#warning AIO has been disabled. #warning AIO has been disabled.
#endif #endif
FlatFileReader::FlatFileReader(bool shareWrite) : shareWrite(shareWrite) FlatFileReader::FlatFileReader(bool shareWrite)
: shareWrite(shareWrite)
{ {
m_blocksize = 2048; m_blocksize = 2048;
m_fd = -1; m_fd = -1;
m_async_read_in_progress = false; m_async_read_in_progress = false;
} }
FlatFileReader::~FlatFileReader(void) FlatFileReader::~FlatFileReader()
{ {
Close(); 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); 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); BeginRead(pBuffer, sector, count);
return FinishRead(); 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; 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) if (!m_async_read_in_progress)
return m_aiocb.aio_nbytes == (size_t)-1 ? -1 : 1; return m_aiocb.aio_nbytes == (size_t)-1 ? -1 : 1;
m_async_read_in_progress = true; 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) while (aio_suspend(aiocb_list, 1, nullptr) == -1 && errno == EINTR)
; ;
return aio_return(&m_aiocb); return aio_return(&m_aiocb);
} }
void FlatFileReader::CancelRead(void) void FlatFileReader::CancelRead()
{ {
if (m_async_read_in_progress) if (m_async_read_in_progress)
{ {
@ -120,7 +123,7 @@ void FlatFileReader::CancelRead(void)
} }
} }
void FlatFileReader::Close(void) void FlatFileReader::Close()
{ {
CancelRead(); CancelRead();
if (m_fd != -1) if (m_fd != -1)
@ -129,7 +132,7 @@ void FlatFileReader::Close(void)
m_fd = -1; 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<u32>(FileSystem::GetPathFileSize(m_filename.c_str()) / m_blocksize);
} }

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -25,6 +25,7 @@
#include "common/Assertions.h" #include "common/Assertions.h"
#include "common/Console.h" #include "common/Console.h"
#include "common/FileSystem.h" #include "common/FileSystem.h"
#include "common/Error.h"
#include "common/HTTPDownloader.h" #include "common/HTTPDownloader.h"
#include "common/HeterogeneousContainers.h" #include "common/HeterogeneousContainers.h"
#include "common/Path.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) 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... // This isn't great, we really want to make it all thread-local...
CDVD = &CDVDapi_Iso; 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; return false;
}
// TODO: we could include the version in the game list? // TODO: we could include the version in the game list?
*disc_type = DoCDVDdetectDiskType(); *disc_type = DoCDVDdetectDiskType();

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -15,6 +15,7 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "AsyncFileReader.h" #include "AsyncFileReader.h"
#include "common/FileSystem.h" #include "common/FileSystem.h"
#include <unistd.h> #include <unistd.h>
@ -29,31 +30,31 @@ FlatFileReader::FlatFileReader(bool shareWrite)
m_aio_context = 0; m_aio_context = 0;
} }
FlatFileReader::~FlatFileReader(void) FlatFileReader::~FlatFileReader()
{ {
Close(); 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); int err = io_setup(64, &m_aio_context);
if (err) if (err)
return false; 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); 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); BeginRead(pBuffer, sector, count);
return FinishRead(); return FinishRead();
} }
void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count) void FlatFileReader::BeginRead(void* pBuffer, u32 sector, u32 count)
{ {
u64 offset; u64 offset;
offset = sector * (s64)m_blocksize + m_dataoffset; 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); io_submit(m_aio_context, 1, &iocbs);
} }
int FlatFileReader::FinishRead(void) int FlatFileReader::FinishRead()
{ {
struct io_event event; struct io_event event;
@ -78,7 +79,7 @@ int FlatFileReader::FinishRead(void)
return event.res; return event.res;
} }
void FlatFileReader::CancelRead(void) void FlatFileReader::CancelRead()
{ {
// Will be done when m_aio_context context is destroyed // Will be done when m_aio_context context is destroyed
// Note: io_cancel exists but need the iocb structure as parameter // Note: io_cancel exists but need the iocb structure as parameter
@ -86,7 +87,7 @@ void FlatFileReader::CancelRead(void)
// struct io_event *result); // struct io_event *result);
} }
void FlatFileReader::Close(void) void FlatFileReader::Close()
{ {
if (m_fd != -1) if (m_fd != -1)
close(m_fd); close(m_fd);
@ -97,11 +98,11 @@ void FlatFileReader::Close(void)
m_aio_context = 0; m_aio_context = 0;
} }
uint FlatFileReader::GetBlockCount(void) const u32 FlatFileReader::GetBlockCount() const
{ {
struct stat sysStatData; struct stat sysStatData;
if (fstat(m_fd, &sysStatData) < 0) if (fstat(m_fd, &sysStatData) < 0)
return 0; return 0;
return static_cast<uint>(sysStatData.st_size / m_blocksize); return static_cast<u32>(sysStatData.st_size / m_blocksize);
} }

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -15,8 +15,10 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "AsyncFileReader.h" #include "AsyncFileReader.h"
#include "common/Assertions.h" #include "common/Assertions.h"
#include "common/FileSystem.h" #include "common/FileSystem.h"
#include "common/Error.h"
#include "common/Path.h" #include "common/Path.h"
#include "common/StringUtil.h" #include "common/StringUtil.h"
@ -120,7 +122,7 @@ void MultipartFileReader::FindParts()
Part* thispart = m_parts + m_numparts; Part* thispart = m_parts + m_numparts;
AsyncFileReader* thisreader = new FlatFileReader(); AsyncFileReader* thisreader = new FlatFileReader();
if (!thisreader->Open(nameparts)) if (!thisreader->Open(nameparts, nullptr))
{ {
delete thisreader; delete thisreader;
break; break;
@ -147,8 +149,9 @@ void MultipartFileReader::FindParts()
//Console.WriteLn( Color_Blue, "isoFile: multi-part ISO loaded (%u parts found)", m_numparts ); //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, // Cannot open a MultipartFileReader directly,
// use DetectMultipart to convert a FlatFileReader // use DetectMultipart to convert a FlatFileReader
return false; return false;

View File

@ -1142,10 +1142,13 @@ bool VMManager::Initialize(VMBootParameters boot_params)
} }
} }
Error error;
Console.WriteLn("Opening CDVD..."); 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; return false;
} }
ScopedGuard close_cdvd(&DoCDVDclose); ScopedGuard close_cdvd(&DoCDVDclose);
@ -1909,7 +1912,8 @@ bool VMManager::ChangeDisc(CDVD_SourceType source, std::string path)
if (!path.empty()) if (!path.empty())
CDVDsys_SetFile(source, std::move(path)); CDVDsys_SetFile(source, std::move(path));
const bool result = DoCDVDopen(); Error error;
const bool result = DoCDVDopen(&error);
if (result) if (result)
{ {
if (source == CDVD_SourceType::NoDisc) 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, Host::AddIconOSDMessage("ChangeDisc", ICON_FA_COMPACT_DISC,
fmt::format( 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); Host::OSD_ERROR_DURATION);
CDVDsys_ChangeSource(old_type); CDVDsys_ChangeSource(old_type);
if (!old_path.empty()) if (!old_path.empty())
CDVDsys_SetFile(old_type, std::move(old_path)); CDVDsys_SetFile(old_type, std::move(old_path));
if (!DoCDVDopen()) if (!DoCDVDopen(&error))
{ {
Host::AddIconOSDMessage("ChangeDisc", ICON_FA_COMPACT_DISC, 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); Host::OSD_CRITICAL_ERROR_DURATION);
CDVDsys_ChangeSource(CDVD_SourceType::NoDisc); CDVDsys_ChangeSource(CDVD_SourceType::NoDisc);
DoCDVDopen(); DoCDVDopen(nullptr);
} }
} }
cdvd.Tray.cdvdActionSeconds = 1; cdvd.Tray.cdvdActionSeconds = 1;

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* 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 * 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- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -15,7 +15,9 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "AsyncFileReader.h" #include "AsyncFileReader.h"
#include "common/StringUtil.h" #include "common/StringUtil.h"
#include "common/Error.h"
FlatFileReader::FlatFileReader(bool shareWrite) : shareWrite(shareWrite) FlatFileReader::FlatFileReader(bool shareWrite) : shareWrite(shareWrite)
{ {
@ -25,14 +27,14 @@ FlatFileReader::FlatFileReader(bool shareWrite) : shareWrite(shareWrite)
asyncInProgress = false; asyncInProgress = false;
} }
FlatFileReader::~FlatFileReader(void) FlatFileReader::~FlatFileReader()
{ {
Close(); 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); hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
@ -49,10 +51,16 @@ bool FlatFileReader::Open(std::string fileName)
FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED, FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED,
NULL); 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; //LARGE_INTEGER offset;
//offset.QuadPart = sector * (__int64)m_blocksize; //offset.QuadPart = sector * (__int64)m_blocksize;
@ -68,7 +76,7 @@ int FlatFileReader::ReadSync(void* pBuffer, uint sector, uint count)
return FinishRead(); return FinishRead();
} }
void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count) void FlatFileReader::BeginRead(void* pBuffer, u32 sector, u32 count)
{ {
LARGE_INTEGER offset; LARGE_INTEGER offset;
offset.QuadPart = sector * (s64)m_blocksize + m_dataoffset; offset.QuadPart = sector * (s64)m_blocksize + m_dataoffset;
@ -84,7 +92,7 @@ void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count)
asyncInProgress = true; asyncInProgress = true;
} }
int FlatFileReader::FinishRead(void) int FlatFileReader::FinishRead()
{ {
DWORD bytes; DWORD bytes;
@ -98,12 +106,12 @@ int FlatFileReader::FinishRead(void)
return bytes; return bytes;
} }
void FlatFileReader::CancelRead(void) void FlatFileReader::CancelRead()
{ {
CancelIo(hOverlappedFile); CancelIo(hOverlappedFile);
} }
void FlatFileReader::Close(void) void FlatFileReader::Close()
{ {
if(asyncInProgress) if(asyncInProgress)
CancelRead(); CancelRead();
@ -118,10 +126,10 @@ void FlatFileReader::Close(void)
hEvent = INVALID_HANDLE_VALUE; hEvent = INVALID_HANDLE_VALUE;
} }
uint FlatFileReader::GetBlockCount(void) const u32 FlatFileReader::GetBlockCount(void) const
{ {
LARGE_INTEGER fileSize; LARGE_INTEGER fileSize;
fileSize.LowPart = GetFileSize(hOverlappedFile, (DWORD*)&(fileSize.HighPart)); fileSize.LowPart = GetFileSize(hOverlappedFile, reinterpret_cast<DWORD*>(&fileSize.HighPart));
return (int)(fileSize.QuadPart / m_blocksize); return static_cast<u32>(fileSize.QuadPart / m_blocksize);
} }