Add support for iterating directories in graphics pack content folders. (#1288)

This commit is contained in:
Skyth (Asilkan) 2024-08-13 16:53:04 +03:00 committed by GitHub
parent a6d8c0fb9f
commit c49296acdc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 73 additions and 9 deletions

View File

@ -3,6 +3,8 @@
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include "../fsc.h"
// path parser and utility class for Wii U paths // path parser and utility class for Wii U paths
// optimized to be allocation-free for common path lengths // optimized to be allocation-free for common path lengths
class FSCPath class FSCPath
@ -119,8 +121,6 @@ public:
template<typename F> template<typename F>
class FSAFileTree class FSAFileTree
{ {
public:
private: private:
enum NODETYPE : uint8 enum NODETYPE : uint8
@ -133,6 +133,7 @@ private:
{ {
std::string name; std::string name;
std::vector<node_t*> subnodes; std::vector<node_t*> subnodes;
size_t fileSize;
F* custom; F* custom;
NODETYPE type; NODETYPE type;
}; };
@ -179,13 +180,54 @@ private:
return newNode; return newNode;
} }
class DirectoryIterator : public FSCVirtualFile
{
public:
DirectoryIterator(node_t* node)
: m_node(node), m_subnodeIndex(0)
{
}
sint32 fscGetType() override
{
return FSC_TYPE_DIRECTORY;
}
bool fscDirNext(FSCDirEntry* dirEntry) override
{
if (m_subnodeIndex >= m_node->subnodes.size())
return false;
const node_t* subnode = m_node->subnodes[m_subnodeIndex];
strncpy(dirEntry->path, subnode->name.c_str(), sizeof(dirEntry->path) - 1);
dirEntry->path[sizeof(dirEntry->path) - 1] = '\0';
dirEntry->isDirectory = subnode->type == FSAFileTree::NODETYPE_DIRECTORY;
dirEntry->isFile = subnode->type == FSAFileTree::NODETYPE_FILE;
dirEntry->fileSize = subnode->type == FSAFileTree::NODETYPE_FILE ? subnode->fileSize : 0;
++m_subnodeIndex;
return true;
}
bool fscRewindDir() override
{
m_subnodeIndex = 0;
return true;
}
private:
node_t* m_node;
size_t m_subnodeIndex;
};
public: public:
FSAFileTree() FSAFileTree()
{ {
rootNode.type = NODETYPE_DIRECTORY; rootNode.type = NODETYPE_DIRECTORY;
} }
bool addFile(std::string_view path, F* custom) bool addFile(std::string_view path, size_t fileSize, F* custom)
{ {
FSCPath p(path); FSCPath p(path);
if (p.GetNodeCount() == 0) if (p.GetNodeCount() == 0)
@ -196,6 +238,7 @@ public:
return false; // node already exists return false; // node already exists
// add file node // add file node
node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.GetNodeName(p.GetNodeCount() - 1)); node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.GetNodeName(p.GetNodeCount() - 1));
fileNode->fileSize = fileSize;
fileNode->custom = custom; fileNode->custom = custom;
return true; return true;
} }
@ -214,6 +257,20 @@ public:
return true; return true;
} }
bool getDirectory(std::string_view path, FSCVirtualFile*& dirIterator)
{
FSCPath p(path);
if (p.GetNodeCount() == 0)
return false;
node_t* node = getByNodePath(p, p.GetNodeCount(), false);
if (node == nullptr)
return false;
if (node->type != NODETYPE_DIRECTORY)
return false;
dirIterator = new DirectoryIterator(node);
return true;
}
bool removeFile(std::string_view path) bool removeFile(std::string_view path)
{ {
FSCPath p(path); FSCPath p(path);

View File

@ -212,4 +212,4 @@ bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTarg
// redirect device // redirect device
void fscDeviceRedirect_map(); void fscDeviceRedirect_map();
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority); void fscDeviceRedirect_add(std::string_view virtualSourcePath, size_t fileSize, const fs::path& targetFilePath, sint32 priority);

View File

@ -11,7 +11,7 @@ struct RedirectEntry
FSAFileTree<RedirectEntry> redirectTree; FSAFileTree<RedirectEntry> redirectTree;
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority) void fscDeviceRedirect_add(std::string_view virtualSourcePath, size_t fileSize, const fs::path& targetFilePath, sint32 priority)
{ {
// check if source already has a redirection // check if source already has a redirection
RedirectEntry* existingEntry; RedirectEntry* existingEntry;
@ -24,7 +24,7 @@ void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& t
delete existingEntry; delete existingEntry;
} }
RedirectEntry* entry = new RedirectEntry(targetFilePath, priority); RedirectEntry* entry = new RedirectEntry(targetFilePath, priority);
redirectTree.addFile(virtualSourcePath, entry); redirectTree.addFile(virtualSourcePath, fileSize, entry);
} }
class fscDeviceTypeRedirect : public fscDeviceC class fscDeviceTypeRedirect : public fscDeviceC
@ -32,8 +32,15 @@ class fscDeviceTypeRedirect : public fscDeviceC
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
{ {
RedirectEntry* redirectionEntry; RedirectEntry* redirectionEntry;
if (redirectTree.getFile(path, redirectionEntry))
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE) && redirectTree.getFile(path, redirectionEntry))
return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus); return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus);
FSCVirtualFile* dirIterator;
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR) && redirectTree.getDirectory(path, dirIterator))
return dirIterator;
return nullptr; return nullptr;
} }

View File

@ -830,7 +830,7 @@ void GraphicPack2::_iterateReplacedFiles(const fs::path& currentPath, bool isAOC
{ {
virtualMountPath = fs::path("vol/content/") / virtualMountPath; virtualMountPath = fs::path("vol/content/") / virtualMountPath;
} }
fscDeviceRedirect_add(virtualMountPath.generic_string(), it.path().generic_string(), m_fs_priority); fscDeviceRedirect_add(virtualMountPath.generic_string(), it.file_size(), it.path().generic_string(), m_fs_priority);
} }
} }
} }