mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-25 18:46:55 +01:00
Add support for iterating directories in graphics pack content folders. (#1288)
This commit is contained in:
parent
a6d8c0fb9f
commit
c49296acdc
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user