mirror of https://github.com/PCSX2/pcsx2.git
Gzip ISO: add cache (50 chunks of 4M)
This commit is contained in:
parent
5771e6eae8
commit
36fe83afcc
|
@ -102,6 +102,91 @@ static void WriteIndexToFile(Access* index, const wxString filename) {
|
||||||
|
|
||||||
/////////// End of complementary utilities for zlib_indexed.c //////////
|
/////////// End of complementary utilities for zlib_indexed.c //////////
|
||||||
|
|
||||||
|
class ChunksCache {
|
||||||
|
public:
|
||||||
|
ChunksCache() : m_size(0), m_entries(0) { SetSize(1); };
|
||||||
|
~ChunksCache() { Drop(); };
|
||||||
|
void SetSize(int numChunks);
|
||||||
|
|
||||||
|
void Take(void* pMallocedSrc, PX_off_t offset, int length, int coverage);
|
||||||
|
int Read(void* pDest, PX_off_t offset, int length);
|
||||||
|
private:
|
||||||
|
class CacheEntry {
|
||||||
|
public:
|
||||||
|
CacheEntry(void* pMallocedSrc, PX_off_t offset, int length, int coverage) :
|
||||||
|
data(pMallocedSrc),
|
||||||
|
offset(offset),
|
||||||
|
size(length),
|
||||||
|
coverage(coverage)
|
||||||
|
{};
|
||||||
|
|
||||||
|
~CacheEntry() { if (data) free(data); };
|
||||||
|
|
||||||
|
void* data;
|
||||||
|
PX_off_t offset;
|
||||||
|
int coverage;
|
||||||
|
int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Drop();
|
||||||
|
CacheEntry** m_entries;
|
||||||
|
int m_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Deallocate everything
|
||||||
|
void ChunksCache::Drop() {
|
||||||
|
if (!m_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < m_size; i++)
|
||||||
|
if (m_entries[i])
|
||||||
|
delete m_entries[i];
|
||||||
|
|
||||||
|
delete[] m_entries;
|
||||||
|
m_entries = 0;
|
||||||
|
m_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discarding the cache is OK for now
|
||||||
|
void ChunksCache::SetSize(int numChunks) {
|
||||||
|
Drop();
|
||||||
|
if (numChunks <= 0)
|
||||||
|
return;
|
||||||
|
m_size = numChunks;
|
||||||
|
m_entries = new CacheEntry*[m_size];
|
||||||
|
for (int i = 0; i < m_size; i++)
|
||||||
|
m_entries[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChunksCache::Take(void* pMallocedSrc, PX_off_t offset, int length, int coverage) {
|
||||||
|
if (!m_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_entries[m_size - 1])
|
||||||
|
delete m_entries[m_size - 1];
|
||||||
|
|
||||||
|
for (int i = m_size - 1; i > 0; i--)
|
||||||
|
m_entries[i] = m_entries[i - 1];
|
||||||
|
|
||||||
|
m_entries[0] = new CacheEntry(pMallocedSrc, offset, length, coverage);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ChunksCache::Read(void* pDest, PX_off_t offset, int length) {
|
||||||
|
for (int i = 0; i < m_size; i++) {
|
||||||
|
CacheEntry* e = m_entries[i];
|
||||||
|
if (e && offset >= e->offset && (offset + length) <= (e->offset + e->coverage)) {
|
||||||
|
int available = std::min((PX_off_t)length, e->offset + e->size - offset);
|
||||||
|
memcpy(pDest, (char*)e->data + offset - e->offset, available);
|
||||||
|
// Move to the top of the list (MRU)
|
||||||
|
for (int j = i; j > 0; j--)
|
||||||
|
m_entries[j] = m_entries[j - 1];
|
||||||
|
m_entries[0] = e;
|
||||||
|
return available;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static wxString iso2indexname(const wxString& isoname) {
|
static wxString iso2indexname(const wxString& isoname) {
|
||||||
return isoname + L".pindex.tmp";
|
return isoname + L".pindex.tmp";
|
||||||
|
@ -114,14 +199,18 @@ static void WarnOldIndex(const wxString& filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SPAN_DEFAULT (1048576L * 4) /* distance between access points when creating a new index */
|
||||||
|
#define CACHED_CHUNKS 50 /* how many span chunks to cache */
|
||||||
|
|
||||||
class GzippedFileReader : public AsyncFileReader
|
class GzippedFileReader : public AsyncFileReader
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(GzippedFileReader);
|
DeclareNoncopyableObject(GzippedFileReader);
|
||||||
public:
|
public:
|
||||||
GzippedFileReader(void) :
|
GzippedFileReader(void) :
|
||||||
m_pIndex(0)
|
m_pIndex(0) {
|
||||||
{ m_blocksize = 2048; };
|
m_blocksize = 2048;
|
||||||
|
m_cache.SetSize(CACHED_CHUNKS);
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~GzippedFileReader(void) { Close(); };
|
virtual ~GzippedFileReader(void) { Close(); };
|
||||||
|
|
||||||
|
@ -146,9 +235,10 @@ public:
|
||||||
virtual void SetBlockSize(uint bytes) { m_blocksize = bytes; }
|
virtual void SetBlockSize(uint bytes) { m_blocksize = bytes; }
|
||||||
virtual void SetDataOffset(uint bytes) { m_dataoffset = bytes; }
|
virtual void SetDataOffset(uint bytes) { m_dataoffset = bytes; }
|
||||||
private:
|
private:
|
||||||
bool OkIndex(); // Verifies thatt we have an index, or try to create one
|
bool OkIndex(); // Verifies that we have an index, or try to create one
|
||||||
int mBytesRead; // Temp sync read result when simulating async read
|
int mBytesRead; // Temp sync read result when simulating async read
|
||||||
Access* m_pIndex; // Quick access index
|
Access* m_pIndex; // Quick access index
|
||||||
|
ChunksCache m_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -157,9 +247,6 @@ bool GzippedFileReader::CanHandle(const wxString& fileName) {
|
||||||
return wxFileName::FileExists(fileName) && fileName.Lower().EndsWith(L".gz");
|
return wxFileName::FileExists(fileName) && fileName.Lower().EndsWith(L".gz");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define SPAN_DEFAULT (1048576L * 2) /* distance between access points when creating a new index */
|
|
||||||
|
|
||||||
bool GzippedFileReader::OkIndex() {
|
bool GzippedFileReader::OkIndex() {
|
||||||
if (m_pIndex)
|
if (m_pIndex)
|
||||||
return true;
|
return true;
|
||||||
|
@ -221,6 +308,9 @@ int GzippedFileReader::FinishRead(void) {
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PTT clock_t
|
||||||
|
#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) {
|
||||||
if (!OkIndex())
|
if (!OkIndex())
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -228,10 +318,26 @@ int GzippedFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
||||||
PX_off_t offset = (s64)sector * m_blocksize + m_dataoffset;
|
PX_off_t offset = (s64)sector * m_blocksize + m_dataoffset;
|
||||||
int bytesToRead = count * m_blocksize;
|
int bytesToRead = count * m_blocksize;
|
||||||
|
|
||||||
|
int res = m_cache.Read(pBuffer, offset, bytesToRead);
|
||||||
|
if (res >= 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
// Not available from cache. Decompress a chunk which is a multiple of span
|
||||||
|
// and at span boundaries, and contains the request.
|
||||||
|
s32 span = m_pIndex->span;
|
||||||
|
PX_off_t start = span * (offset / span);
|
||||||
|
PX_off_t end = span * (1 + (offset + bytesToRead - 1) / span);
|
||||||
|
void* chunk = malloc(end - start);
|
||||||
|
|
||||||
|
PTT s = NOW();
|
||||||
FILE* in = fopen(m_filename.ToUTF8(), "rb");
|
FILE* in = fopen(m_filename.ToUTF8(), "rb");
|
||||||
int res = extract(in, m_pIndex, offset, (unsigned char*)pBuffer, bytesToRead);
|
res = extract(in, m_pIndex, start, (unsigned char*)chunk, end - start);
|
||||||
|
m_cache.Take(chunk, start, res, end - start);
|
||||||
fclose(in);
|
fclose(in);
|
||||||
return res;
|
Console.WriteLn("gzip: extracting %1.1f MB -> %d ms", (float)(end - start) / 1024 / 1024, (int)(NOW()- s));
|
||||||
|
|
||||||
|
// The cache now has a chunk which satisfies this request. Recurse (once)
|
||||||
|
return ReadSync(pBuffer, sector, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GzippedFileReader::Close() {
|
void GzippedFileReader::Close() {
|
||||||
|
|
|
@ -238,6 +238,7 @@ set(pcsx2CDVDSources
|
||||||
CDVD/CDVDisoReader.cpp
|
CDVD/CDVDisoReader.cpp
|
||||||
CDVD/InputIsoFile.cpp
|
CDVD/InputIsoFile.cpp
|
||||||
CDVD/OutputIsoFile.cpp
|
CDVD/OutputIsoFile.cpp
|
||||||
|
CDVD/CompressedFileReader.cpp
|
||||||
CDVD/IsoFS/IsoFile.cpp
|
CDVD/IsoFS/IsoFile.cpp
|
||||||
CDVD/IsoFS/IsoFSCDVD.cpp
|
CDVD/IsoFS/IsoFSCDVD.cpp
|
||||||
CDVD/IsoFS/IsoFS.cpp
|
CDVD/IsoFS/IsoFS.cpp
|
||||||
|
@ -250,6 +251,7 @@ set(pcsx2CDVDHeaders
|
||||||
CDVD/CDVD.h
|
CDVD/CDVD.h
|
||||||
CDVD/CDVD_internal.h
|
CDVD/CDVD_internal.h
|
||||||
CDVD/CDVDisoReader.h
|
CDVD/CDVDisoReader.h
|
||||||
|
CDVD/zlib_indexed.c
|
||||||
CDVD/IsoFileFormats.h
|
CDVD/IsoFileFormats.h
|
||||||
CDVD/IsoFS/IsoDirectory.h
|
CDVD/IsoFS/IsoDirectory.h
|
||||||
CDVD/IsoFS/IsoFileDescriptor.h
|
CDVD/IsoFS/IsoFileDescriptor.h
|
||||||
|
|
Loading…
Reference in New Issue