From 20bb55e1cbffadd6ac437693ec857cd277f47bb2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 31 Mar 2013 20:58:24 -0700 Subject: [PATCH 1/2] Speed up reading multiple isos in a row. --- Core/FileSystems/ISOFileSystem.cpp | 27 ++++++++++++++++++++++++--- Core/FileSystems/ISOFileSystem.h | 7 ++++++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 09de15ea4d..40842d2b5d 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -131,6 +131,8 @@ struct VolDescriptor #pragma pack(pop) +std::list ISOFileSystem::entryFreeList; + ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevice) { blockDevice = _blockDevice; @@ -156,7 +158,7 @@ ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevic ERROR_LOG(FILESYS, "ISO looks bogus? trying anyway..."); } - treeroot = new TreeEntry; + treeroot = GetTreeEntry(); treeroot->isDirectory = true; treeroot->startingPosition = 0; treeroot->size = 0; @@ -173,7 +175,7 @@ ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevic ISOFileSystem::~ISOFileSystem() { delete blockDevice; - delete treeroot; + ReleaseTreeEntry(treeroot); } void ISOFileSystem::ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root) @@ -204,7 +206,7 @@ void ISOFileSystem::ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root) bool isFile = (dir.flags & 2) ? false : true; bool relative; - TreeEntry *e = new TreeEntry(); + TreeEntry *e = GetTreeEntry(); if (dir.identifierLength == 1 && (dir.firstIdChar == '\x00' || dir.firstIdChar == '.')) { e->name = "."; @@ -591,6 +593,25 @@ std::string ISOFileSystem::EntryFullPath(TreeEntry *e) return path; } +ISOFileSystem::TreeEntry *ISOFileSystem::GetTreeEntry() +{ + if (entryFreeList.empty()) + return new TreeEntry(); + else + { + TreeEntry *entry = entryFreeList.back(); + entryFreeList.pop_back(); + return entry; + } +} + +void ISOFileSystem::ReleaseTreeEntry(ISOFileSystem::TreeEntry *entry) +{ + entry->name.clear(); + entry->children.clear(); + entryFreeList.push_back(entry); +} + void ISOFileSystem::DoState(PointerWrap &p) { int n = (int) entries.size(); diff --git a/Core/FileSystems/ISOFileSystem.h b/Core/FileSystems/ISOFileSystem.h index 96f8b3f39e..a35f91d75b 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -19,6 +19,7 @@ #include #include +#include #include "FileSystem.h" @@ -53,7 +54,7 @@ private: ~TreeEntry() { for (unsigned int i=0; i entryFreeList; + static TreeEntry *GetTreeEntry(); + static void ReleaseTreeEntry(TreeEntry *entry); }; From d11a5debcb2ebd9f69e5de5d914aeb3a5afac471 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 31 Mar 2013 21:35:30 -0700 Subject: [PATCH 2/2] Add a way to restrict ISO reading to a single path. This is for GameInfoCache. --- Core/FileSystems/ISOFileSystem.cpp | 30 +++++++++++++++++++++++++----- Core/FileSystems/ISOFileSystem.h | 8 ++++++-- UI/GameInfoCache.cpp | 2 +- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 40842d2b5d..41915a1a2b 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -133,8 +133,21 @@ struct VolDescriptor std::list ISOFileSystem::entryFreeList; -ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevice) +ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevice, std::string _restrictPath) { + if (!_restrictPath.empty()) + { + size_t pos = _restrictPath.find_first_not_of('/'); + while (!_restrictPath.empty()) + { + size_t endPos = _restrictPath.find_first_of('/', pos); + if (pos != endPos) + restrictTree.push_back(_restrictPath.substr(pos, endPos)); + pos = _restrictPath.find_first_not_of('/', endPos); + _restrictPath.erase(0, pos); + } + } + blockDevice = _blockDevice; hAlloc = _hAlloc; @@ -169,7 +182,7 @@ ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevic u32 rootSector = desc.root.firstDataSectorLE; u32 rootSize = desc.root.dataLengthLE; - ReadDirectory(rootSector, rootSize, treeroot); + ReadDirectory(rootSector, rootSize, treeroot, 0); } ISOFileSystem::~ISOFileSystem() @@ -178,7 +191,7 @@ ISOFileSystem::~ISOFileSystem() ReleaseTreeEntry(treeroot); } -void ISOFileSystem::ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root) +void ISOFileSystem::ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root, size_t level) { for (u32 secnum = startsector, endsector = dirsize/2048 + startsector; secnum < endsector; ++secnum) { @@ -198,7 +211,7 @@ void ISOFileSystem::ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root) if (offset + IDENTIFIER_OFFSET + dir.identifierLength > 2048) { ERROR_LOG(FILESYS, "Directory entry crosses sectors, corrupt iso?"); - break; + return; } offset += dir.size; @@ -241,7 +254,14 @@ void ISOFileSystem::ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root) } else { - ReadDirectory(dir.firstDataSectorLE, dir.dataLengthLE, e); + bool doRecurse = true; + if (!restrictTree.empty()) + doRecurse = level < restrictTree.size() && restrictTree[level] == e->name; + + if (doRecurse) + ReadDirectory(dir.firstDataSectorLE, dir.dataLengthLE, e, level + 1); + else + continue; } } root->children.push_back(e); diff --git a/Core/FileSystems/ISOFileSystem.h b/Core/FileSystems/ISOFileSystem.h index a35f91d75b..1ec9be28ce 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "FileSystem.h" @@ -29,7 +30,7 @@ class ISOFileSystem : public IFileSystem { public: - ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevice); + ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevice, std::string _restrictPath = ""); ~ISOFileSystem(); void DoState(PointerWrap &p); std::vector GetDirListing(std::string path); @@ -87,7 +88,10 @@ private: TreeEntry entireISO; - void ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root); + // Don't use this in the emu, not savestated. + std::vector restrictTree; + + void ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root, size_t level); TreeEntry *GetFromPath(std::string path, bool catchError=true); std::string EntryFullPath(TreeEntry *e); diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index daab7ccf77..701a4554b4 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -120,7 +120,7 @@ again: BlockDevice *bd = constructBlockDevice(gamePath.c_str()); if (!bd) return 0; // nothing to do here.. - ISOFileSystem umd(&handles, bd); + ISOFileSystem umd(&handles, bd, "/PSP_GAME"); GameInfo *info = new GameInfo(); info->wantBG = wantBG;