Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading