CDVD: Use ThreadedFileReader for block dumps

This commit is contained in:
Stenzek 2024-05-16 20:02:18 +10:00 committed by Connor McLaughlin
parent 89c4e2c1a4
commit f0ae33d61e
7 changed files with 100 additions and 112 deletions

View File

@ -95,40 +95,3 @@ public:
void SetBlockSize(u32 bytes) override { m_blocksize = bytes; } void SetBlockSize(u32 bytes) override { m_blocksize = bytes; }
void SetDataOffset(u32 bytes) override { m_dataoffset = bytes; } void SetDataOffset(u32 bytes) override { m_dataoffset = bytes; }
}; };
class BlockdumpFileReader : public AsyncFileReader
{
DeclareNoncopyableObject(BlockdumpFileReader);
std::FILE* m_file;
// total number of blocks in the ISO image (including all parts)
u32 m_blocks;
s32 m_blockofs;
// index table
std::unique_ptr<u32[]> m_dtable;
int m_dtablesize;
int m_lresult;
public:
BlockdumpFileReader();
~BlockdumpFileReader() override;
bool Open(std::string filename, Error* error) override;
int ReadSync(void* pBuffer, u32 sector, u32 count) override;
void BeginRead(void* pBuffer, u32 sector, u32 count) override;
int FinishRead() override;
void CancelRead() override;
void Close() override;
u32 GetBlockCount() const override;
static bool DetectBlockdump(AsyncFileReader* reader);
s32 GetBlockOffset() { return m_blockofs; }
};

View File

@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team // SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+ // SPDX-License-Identifier: LGPL-3.0+
#include "AsyncFileReader.h" #include "BlockdumpFileReader.h"
#include "IsoFileFormats.h" #include "IsoFileFormats.h"
#include "common/Assertions.h" #include "common/Assertions.h"
@ -27,8 +27,7 @@ bool BlockdumpFileReader::DetectBlockdump(AsyncFileReader* reader)
reader->SetBlockSize(1); reader->SetBlockSize(1);
char buf[4] = {0}; char buf[4] = {0};
bool isbd = (reader->ReadSync(buf, 0, sizeof(buf)) == 4 bool isbd = (reader->ReadSync(buf, 0, sizeof(buf)) == 4 && std::memcmp(buf, "BDV2", sizeof(buf)) == 0);
&& std::memcmp(buf, "BDV2", sizeof(buf)) == 0);
if (!isbd) if (!isbd)
reader->SetBlockSize(oldbs); reader->SetBlockSize(oldbs);
@ -36,21 +35,14 @@ bool BlockdumpFileReader::DetectBlockdump(AsyncFileReader* reader)
return isbd; return isbd;
} }
BlockdumpFileReader::BlockdumpFileReader() BlockdumpFileReader::BlockdumpFileReader() = default;
: m_file(NULL)
, m_blocks(0)
, m_blockofs(0)
, m_dtablesize(0)
, m_lresult(0)
{
}
BlockdumpFileReader::~BlockdumpFileReader() BlockdumpFileReader::~BlockdumpFileReader()
{ {
Close(); Close();
} }
bool BlockdumpFileReader::Open(std::string filename, Error* error) bool BlockdumpFileReader::Open2(std::string filename, Error* error)
{ {
char signature[4]; char signature[4];
@ -60,30 +52,32 @@ bool BlockdumpFileReader::Open(std::string filename, Error* error)
if (std::fread(signature, sizeof(signature), 1, m_file) != 1 || std::memcmp(signature, "BDV2", sizeof(signature)) != 0) 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."); Error::SetStringView(error, "Block dump signature is invalid.");
return false; return false;
} }
//m_flags = ISOFLAGS_BLOCKDUMP_V2; //m_flags = ISOFLAGS_BLOCKDUMP_V2;
if (std::fread(&m_blocksize, sizeof(m_blocksize), 1, m_file) != 1 if (std::fread(&m_dblocksize, sizeof(m_dblocksize), 1, m_file) != 1 ||
|| 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."); Error::SetStringView(error, "Failed to read block dump information.");
return false; return false;
} }
m_blocksize = m_dblocksize;
const s64 flen = FileSystem::FSize64(m_file); const s64 flen = FileSystem::FSize64(m_file);
const s64 datalen = flen - BlockDumpHeaderSize; const s64 datalen = flen - BlockDumpHeaderSize;
pxAssert((datalen % (m_blocksize + 4)) == 0); pxAssert((datalen % (m_dblocksize + 4)) == 0);
m_dtablesize = datalen / (m_blocksize + 4); m_dtablesize = datalen / (m_dblocksize + 4);
m_dtable = std::make_unique<u32[]>(m_dtablesize); m_dtable = std::make_unique_for_overwrite<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."); Error::SetStringView(error, "Failed to seek to block dump data.");
return false; return false;
} }
@ -100,7 +94,7 @@ bool BlockdumpFileReader::Open(std::string filename, Error* error)
{ {
m_dtable[i++] = *reinterpret_cast<u32*>(buffer.get() + off); m_dtable[i++] = *reinterpret_cast<u32*>(buffer.get() + off);
off += 4; off += 4;
off += m_blocksize; off += m_dblocksize;
} }
off -= has; off -= has;
@ -110,74 +104,60 @@ bool BlockdumpFileReader::Open(std::string filename, Error* error)
return true; return true;
} }
int BlockdumpFileReader::ReadSync(void* pBuffer, u32 lsn, u32 count) ThreadedFileReader::Chunk BlockdumpFileReader::ChunkForOffset(u64 offset)
{ {
u8* dst = (u8*)pBuffer; Chunk chunk = {};
// Console.WriteLn("_isoReadBlockD %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs); chunk.chunkID = offset / m_dblocksize;
chunk.length = m_dblocksize;
chunk.offset = chunk.chunkID * m_dblocksize;
return chunk;
}
while (count > 0) int BlockdumpFileReader::ReadChunk(void* dst, s64 blockID)
{
pxAssert(blockID >= 0 && blockID < static_cast<s64>(m_blocks));
const u32 lsn = static_cast<u32>(blockID);
// Console.WriteLn("_isoReadBlockD %u, blocksize=%u, blockofs=%u\n", static_cast<u32>(blockID), iso->blocksize, iso->blockofs);
for (int i = 0; i < m_dtablesize; ++i)
{ {
bool ok = false; if (m_dtable[i] != lsn)
for (int i = 0; i < m_dtablesize; ++i) continue;
{
if (m_dtable[i] != lsn)
continue;
// We store the LSN (u32) along with each block inside of blockdumps, so the // We store the LSN (u32) along with each block inside of blockdumps, so the
// seek position ends up being based on (m_blocksize + 4) instead of just m_blocksize. // seek position ends up being based on (m_blocksize + 4) instead of just m_blocksize.
#ifdef PCSX2_DEBUG #ifdef PCSX2_DEBUG
u32 check_lsn = 0; u32 check_lsn = 0;
FileSystem::FSeek64(m_file, BlockDumpHeaderSize + (i * (m_blocksize + 4)), SEEK_SET); FileSystem::FSeek64(m_file, BlockDumpHeaderSize + (i * (m_blocksize + 4)), SEEK_SET);
std::fread(&check_lsn, sizeof(check_lsn), 1, m_file); std::fread(&check_lsn, sizeof(check_lsn), 1, m_file);
pxAssert(check_lsn == lsn); pxAssert(check_lsn == lsn);
#else #else
if (FileSystem::FSeek64(m_file, BlockDumpHeaderSize + (i * (m_blocksize + 4)) + 4, SEEK_SET) != 0) if (FileSystem::FSeek64(m_file, BlockDumpHeaderSize + (i * (m_blocksize + 4)) + 4, SEEK_SET) != 0)
break; return 0;
#endif #endif
if (std::fread(dst, m_blocksize, 1, m_file) != 1) if (std::fread(dst, m_blocksize, 1, m_file) != 1)
break; return 0;
else
ok = true; return m_blocksize;
break;
}
if (!ok)
{
Console.WriteLn("Block %u not found in dump", lsn);
return -1;
}
count--;
lsn++;
dst += m_blocksize;
} }
return 0; // Either we hit a sector that's not in the dump, and needed, or the threaded reader is just reading ahead.
return -1;
} }
void BlockdumpFileReader::BeginRead(void* pBuffer, u32 sector, u32 count) void BlockdumpFileReader::Close2()
{ {
m_lresult = ReadSync(pBuffer, sector, count); if (!m_file)
} return;
int BlockdumpFileReader::FinishRead() std::fclose(m_file);
{ m_file = nullptr;
return m_lresult; m_dtable.reset();
} m_dtablesize = 0;
m_dblocksize = 0;
void BlockdumpFileReader::CancelRead() m_blocks = 0;
{
}
void BlockdumpFileReader::Close(void)
{
if (m_file)
{
std::fclose(m_file);
m_file = nullptr;
}
} }
u32 BlockdumpFileReader::GetBlockCount() const u32 BlockdumpFileReader::GetBlockCount() const

View File

@ -0,0 +1,39 @@
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+
#include "CDVD/ThreadedFileReader.h"
#include <cstdio>
class BlockdumpFileReader final : public ThreadedFileReader
{
DeclareNoncopyableObject(BlockdumpFileReader);
std::FILE* m_file = nullptr;
// total number of blocks in the ISO image (including all parts)
u32 m_dblocksize = 0;
u32 m_blocks = 0;
s32 m_blockofs = 0;
// index table
std::unique_ptr<u32[]> m_dtable;
int m_dtablesize = 0;
public:
BlockdumpFileReader();
~BlockdumpFileReader() override;
bool Open2(std::string filename, Error* error) override;
Chunk ChunkForOffset(u64 offset) override;
int ReadChunk(void* dst, s64 blockID) override;
void Close2() override;
u32 GetBlockCount() const override;
static bool DetectBlockdump(AsyncFileReader* reader);
s32 GetBlockOffset() { return m_blockofs; }
};

View File

@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team // SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+ // SPDX-License-Identifier: LGPL-3.0+
#include "CDVD/BlockdumpFileReader.h"
#include "CDVD/IsoFileFormats.h" #include "CDVD/IsoFileFormats.h"
#include "Config.h" #include "Config.h"
#include "Host.h" #include "Host.h"

View File

@ -225,6 +225,7 @@ set(pcsx2CDVDSources
# CDVD headers # CDVD headers
set(pcsx2CDVDHeaders set(pcsx2CDVDHeaders
CDVD/BlockdumpFileReader.h
CDVD/Ps1CD.h CDVD/Ps1CD.h
CDVD/CDVDcommon.h CDVD/CDVDcommon.h
CDVD/CDVD.h CDVD/CDVD.h

View File

@ -465,6 +465,7 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="Achievements.h" /> <ClInclude Include="Achievements.h" />
<ClInclude Include="AsyncFileReader.h" /> <ClInclude Include="AsyncFileReader.h" />
<ClInclude Include="CDVD\BlockdumpFileReader.h" />
<ClInclude Include="CDVD\CDVDdiscReader.h" /> <ClInclude Include="CDVD\CDVDdiscReader.h" />
<ClInclude Include="CDVD\ChunksCache.h" /> <ClInclude Include="CDVD\ChunksCache.h" />
<ClInclude Include="CDVD\CompressedFileReader.h" /> <ClInclude Include="CDVD\CompressedFileReader.h" />

View File

@ -2318,6 +2318,9 @@
<ClInclude Include="Host\AudioStreamTypes.h"> <ClInclude Include="Host\AudioStreamTypes.h">
<Filter>Misc\Host</Filter> <Filter>Misc\Host</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="CDVD\BlockdumpFileReader.h">
<Filter>System\ISO</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuildStep Include="rdebug\deci2.h"> <CustomBuildStep Include="rdebug\deci2.h">