diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 09de15ea4d..41915a1a2b 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -131,8 +131,23 @@ struct VolDescriptor #pragma pack(pop) -ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevice) +std::list ISOFileSystem::entryFreeList; + +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; @@ -156,7 +171,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; @@ -167,16 +182,16 @@ 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() { delete blockDevice; - delete treeroot; + 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) { @@ -196,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; @@ -204,7 +219,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 = "."; @@ -239,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); @@ -591,6 +613,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..1ec9be28ce 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -19,6 +19,8 @@ #include #include +#include +#include #include "FileSystem.h" @@ -28,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); @@ -53,7 +55,7 @@ private: ~TreeEntry() { for (unsigned int i=0; i 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); + + static std::list entryFreeList; + static TreeEntry *GetTreeEntry(); + static void ReleaseTreeEntry(TreeEntry *entry); }; diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index f1821fcc60..461c670c61 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -123,7 +123,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;