Skip to content

Commit

Permalink
Add support for iterating directories in graphics pack content folder…
Browse files Browse the repository at this point in the history
…s. (#1288)
  • Loading branch information
blueskythlikesclouds authored Aug 13, 2024
1 parent a6d8c0f commit c49296a
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 9 deletions.
65 changes: 61 additions & 4 deletions src/Cafe/Filesystem/FST/fstUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -119,9 +121,7 @@ class FSCPath
template<typename F>
class FSAFileTree
{
public:

private:
private:

enum NODETYPE : uint8
{
Expand All @@ -133,6 +133,7 @@ class FSAFileTree
{
std::string name;
std::vector<node_t*> subnodes;
size_t fileSize;
F* custom;
NODETYPE type;
};
Expand Down Expand Up @@ -179,13 +180,54 @@ class FSAFileTree
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)
Expand All @@ -196,6 +238,7 @@ class FSAFileTree
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;
}
Expand All @@ -214,6 +257,20 @@ class FSAFileTree
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);
Expand Down
2 changes: 1 addition & 1 deletion src/Cafe/Filesystem/fsc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
13 changes: 10 additions & 3 deletions src/Cafe/Filesystem/fscDeviceRedirect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -24,16 +24,23 @@ 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
{
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;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Cafe/GraphicPack/GraphicPack2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down

0 comments on commit c49296a

Please sign in to comment.