mirror of https://github.com/PCSX2/pcsx2.git
CDVD: Report open errors to host
This commit is contained in:
parent
93a4e67813
commit
a9959bcd62
|
@ -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
|
||||||
|
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue