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 "../fsc.h"
// path parser and utility class for Wii U paths
// optimized to be allocation-free for common path lengths
class FSCPath
@ -119,9 +121,7 @@ public:
template<typename F>
class FSAFileTree
{
public:
private:
private:
enum NODETYPE : uint8
{
@ -133,6 +133,7 @@ private:
{
std::string name;
std::vector<node_t*> subnodes;
size_t fileSize;
F* custom;
NODETYPE type;
};
@ -179,13 +180,54 @@ private:
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:
FSAFileTree()
{
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);
if (p.GetNodeCount() == 0)
@ -196,6 +238,7 @@ public:
return false; // node already exists
// add file node
node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.GetNodeName(p.GetNodeCount() - 1));
fileNode->fileSize = fileSize;
fileNode->custom = custom;
return true;
}
@ -214,6 +257,20 @@ public:
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)
{
FSCPath p(path);

View file

@ -212,4 +212,4 @@ bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTarg
// redirect device
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;
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
RedirectEntry* existingEntry;
@ -24,7 +24,7 @@ void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& t
delete existingEntry;
}
RedirectEntry* entry = new RedirectEntry(targetFilePath, priority);
redirectTree.addFile(virtualSourcePath, entry);
redirectTree.addFile(virtualSourcePath, fileSize, entry);
}
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
{
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);
FSCVirtualFile* dirIterator;
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR) && redirectTree.getDirectory(path, dirIterator))
return dirIterator;
return nullptr;
}

View file

@ -830,7 +830,7 @@ void GraphicPack2::_iterateReplacedFiles(const fs::path& currentPath, bool isAOC
{
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);
}
}
}