mirror of
https://github.com/izzy2lost/WeeU.git
synced 2026-07-06 00:19:59 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61a3b07697 | ||
|
|
6cf5dc9a56 | ||
|
|
0afa2d75aa | ||
|
|
b5963afbb5 | ||
|
|
9a60979242 | ||
|
|
d4879da95c | ||
|
|
b47b38448c | ||
|
|
694b9ec495 | ||
|
|
08db65bd5a | ||
|
|
13aa0a4fd0 | ||
|
|
4c6f22ba39 | ||
|
|
3349d7b424 | ||
|
|
680beaaf21 | ||
|
|
168ecf8825 | ||
|
|
1ce629126a | ||
|
|
b8462cec8b | ||
|
|
0e0602e8d9 | ||
|
|
cf598e38c1 | ||
|
|
6dda53e84f | ||
|
|
045a059742 | ||
|
|
76313fc238 | ||
|
|
1e851fe7e2 | ||
|
|
f032088902 | ||
|
|
6cdb6eed17 | ||
|
|
4eaa600b57 | ||
|
|
4d1be950e3 | ||
|
|
b752d2eddd | ||
|
|
0a1985e481 | ||
|
|
e20bfd00ec | ||
|
|
f8b5024c09 |
@@ -1,18 +1,6 @@
|
||||
name: Build Cemu
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
push:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
branches:
|
||||
- main
|
||||
workflow_call:
|
||||
inputs:
|
||||
deploymode:
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
name: Build check
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
push:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/build.yml
|
||||
with:
|
||||
deploymode: release
|
||||
experimentalversion: 999999
|
||||
@@ -0,0 +1,42 @@
|
||||
name: Generate translation template
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
push:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
generate-pot:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout repo"
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: "Install gettext"
|
||||
run: |
|
||||
sudo apt update -qq
|
||||
sudo apt install -y gettext
|
||||
|
||||
- name: "Generate POT file using xgettext"
|
||||
run: >
|
||||
find src -name *.cpp -o -name *.hpp -o -name *.h |
|
||||
xargs xgettext --from-code=utf-8
|
||||
-k_ -kwxTRANSLATE -w 100
|
||||
--check=space-ellipsis --omit-header
|
||||
-o cemu.pot
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: POT file
|
||||
path: ./cemu.pot
|
||||
if-no-files-found: error
|
||||
@@ -32,6 +32,7 @@ bin/mlc01/*
|
||||
bin/settings.xml
|
||||
bin/title_list_cache.xml
|
||||
bin/debugger/*
|
||||
bin/sdcard/*
|
||||
|
||||
!bin/shaderCache/info.txt
|
||||
bin/shaderCache/*
|
||||
|
||||
@@ -14,7 +14,7 @@ Instructions:
|
||||
2. Launch `Cemu/generate_vs_solution.bat`.
|
||||
- If you installed VS to a custom location or use VS 2019, you may need to manually change the path inside the .bat file
|
||||
3. Wait until it's done, then open `Cemu/build/Cemu.sln` in Visual Studio
|
||||
4. Then build the solution and once finished you can run and debug it, or build it and check the /bin folder for the final Cemu.exe.
|
||||
4. Then build the solution and once finished you can run and debug it, or build it and check the /bin folder for the final Cemu_release.exe.
|
||||
|
||||
You can also skip steps 3-5 and open the root folder of the cloned repo directly in Visual Studio (as a folder) and use the built-in cmake support but be warned that cmake support in VS can be a bit finicky.
|
||||
|
||||
@@ -42,7 +42,7 @@ Additionally, for ubuntu 20.04 only:
|
||||
2. `cd Cemu`
|
||||
3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -G Ninja`
|
||||
4. `cmake --build build`
|
||||
5. You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu`.
|
||||
5. You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu_release`.
|
||||
|
||||
#### Using GCC
|
||||
While we use and test Cemu using clang, using GCC might work better with your distro (they should be fairly similar performance/issues wise and should only be considered if compilation is the issue).
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
[](https://github.com/cemu-project/Cemu/actions/workflows/build.yml)
|
||||
[](https://discord.gg/5psYsup)
|
||||
[](https://matrix.to/#/#dev:cemu.info)
|
||||
|
||||
This is the code repository of Cemu, a Wii U emulator that is able to run most Wii U games and homebrew in a playable state.
|
||||
It's written in C/C++ and is being actively developed with new features and fixes to increase compatibility, convenience and usability.
|
||||
@@ -22,7 +23,7 @@ Cemu is currently only available for 64-bit Windows and Linux devices.
|
||||
|
||||
## Download
|
||||
|
||||
You can download the latest Cemu releases from the [Github Releases](https://github.com/cemu-project/Cemu/releases/) or from [Cemu's website](https://cemu.info).
|
||||
You can download the latest Cemu releases from the [GitHub Releases](https://github.com/cemu-project/Cemu/releases/) or from [Cemu's website](https://cemu.info).
|
||||
|
||||
Cemu is currently only available in a portable format so no installation is required besides extracting it in a safe place.
|
||||
|
||||
@@ -36,8 +37,8 @@ To compile Cemu yourself on Windows or Linux, view the [BUILD.md file](/BUILD.md
|
||||
|
||||
## Issues
|
||||
|
||||
Issues with the emulator should be filed using [Github Issues](https://github.com/cemu-project/Cemu/issues).
|
||||
The old bug tracker can be found at [bugs.cemu.info](http://bugs.cemu.info) and still contains relevant issues and feature suggestions.
|
||||
Issues with the emulator should be filed using [GitHub Issues](https://github.com/cemu-project/Cemu/issues).
|
||||
The old bug tracker can be found at [bugs.cemu.info](https://bugs.cemu.info) and still contains relevant issues and feature suggestions.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "config/ActiveSettings.h"
|
||||
#include "Cafe/IOSU/legacy/iosu_crypto.h"
|
||||
#include "Common/filestream.h"
|
||||
#include "Common/FileStream.h"
|
||||
|
||||
#include <random>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "Cafe/Filesystem/FST/FST.h"
|
||||
|
||||
#include "Common/filestream.h"
|
||||
#include "Common/FileStream.h"
|
||||
|
||||
#include "GamePatch.h"
|
||||
|
||||
@@ -209,7 +209,7 @@ void InfoLog_TitleLoaded()
|
||||
fs::path effectiveSavePath = getTitleSavePath();
|
||||
std::error_code ec;
|
||||
const bool saveDirExists = fs::exists(effectiveSavePath, ec);
|
||||
cemuLog_force("Save path: {}{}", _utf8Wrapper(effectiveSavePath), saveDirExists ? "" : " (not present)");
|
||||
cemuLog_force("Save path: {}{}", _pathToUtf8(effectiveSavePath), saveDirExists ? "" : " (not present)");
|
||||
|
||||
// log shader cache name
|
||||
cemuLog_log(LogType::Force, "Shader cache file: shaderCache/transferable/{:016x}.bin", titleId);
|
||||
@@ -617,7 +617,7 @@ namespace CafeSystem
|
||||
sLaunchModeIsStandalone = true;
|
||||
cemuLog_log(LogType::Force, "Launching executable in standalone mode due to incorrect layout or missing meta files");
|
||||
fs::path executablePath = path;
|
||||
std::string dirName = _utf8Wrapper(executablePath.parent_path().filename());
|
||||
std::string dirName = _pathToUtf8(executablePath.parent_path().filename());
|
||||
if (boost::iequals(dirName, "code"))
|
||||
{
|
||||
// check for content folder
|
||||
@@ -626,18 +626,18 @@ namespace CafeSystem
|
||||
if (fs::is_directory(contentPath, ec))
|
||||
{
|
||||
// mounting content folder
|
||||
bool r = FSCDeviceHostFS_Mount(std::string("/vol/content").c_str(), boost::nowide::widen(_utf8Wrapper(contentPath)).c_str(), FSC_PRIORITY_BASE);
|
||||
bool r = FSCDeviceHostFS_Mount(std::string("/vol/content").c_str(), _pathToUtf8(contentPath), FSC_PRIORITY_BASE);
|
||||
if (!r)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "Failed to mount {}", _utf8Wrapper(contentPath).c_str());
|
||||
cemuLog_log(LogType::Force, "Failed to mount {}", _pathToUtf8(contentPath));
|
||||
return STATUS_CODE::UNABLE_TO_MOUNT;
|
||||
}
|
||||
}
|
||||
}
|
||||
// mount code folder to a virtual temporary path
|
||||
FSCDeviceHostFS_Mount(std::string("/internal/code/").c_str(), boost::nowide::widen(_utf8Wrapper(executablePath.parent_path())).c_str(), FSC_PRIORITY_BASE);
|
||||
FSCDeviceHostFS_Mount(std::string("/internal/code/").c_str(), _pathToUtf8(executablePath.parent_path()), FSC_PRIORITY_BASE);
|
||||
std::string internalExecutablePath = "/internal/code/";
|
||||
internalExecutablePath.append(_utf8Wrapper(executablePath.filename()));
|
||||
internalExecutablePath.append(_pathToUtf8(executablePath.filename()));
|
||||
_pathToExecutable = internalExecutablePath;
|
||||
// since a lot of systems (including save folder location) rely on a TitleId, we derive a placeholder id from the executable hash
|
||||
auto execData = fsc_extractFile(_pathToExecutable.c_str());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "Common/precompiled.h"
|
||||
#include "Common/filestream.h"
|
||||
#include "Common/FileStream.h"
|
||||
#include "Cemu/ncrypto/ncrypto.h"
|
||||
#include "Cafe/Filesystem/WUD/wud.h"
|
||||
#include "util/crypto/aes128.h"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "config/ActiveSettings.h"
|
||||
#include "util/crypto/aes128.h"
|
||||
#include "Common/filestream.h"
|
||||
#include "Common/FileStream.h"
|
||||
#include "util/helpers/StringHelpers.h"
|
||||
|
||||
std::mutex mtxKeyCache;
|
||||
|
||||
+177
-361
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "wud.h"
|
||||
#include "Common/filestream.h"
|
||||
#include "Common/FileStream.h"
|
||||
|
||||
wud_t* wud_open(const fs::path& path)
|
||||
{
|
||||
|
||||
+48
-143
@@ -1,14 +1,15 @@
|
||||
#include "Cafe/Filesystem/fsc.h"
|
||||
#include "Cafe/Filesystem/FST/fstUtil.h"
|
||||
|
||||
struct FSCMountPathNode
|
||||
{
|
||||
std::string path;
|
||||
std::vector<FSCMountPathNode*> subnodes;
|
||||
FSCMountPathNode* parent;
|
||||
// device target and path (if list_subnodes is nullptr)
|
||||
// device target and path (if subnodes is empty)
|
||||
fscDeviceC* device{ nullptr };
|
||||
void* ctx{ nullptr };
|
||||
std::wstring targetPath;
|
||||
std::string deviceTargetPath; // the destination base path for the device, utf8
|
||||
// priority
|
||||
sint32 priority{};
|
||||
|
||||
@@ -24,7 +25,7 @@ struct FSCMountPathNode
|
||||
}
|
||||
};
|
||||
|
||||
// compare two file or directory names using FS rules
|
||||
// compare two file or directory names using FSA rules
|
||||
bool FSA_CompareNodeName(std::string_view a, std::string_view b)
|
||||
{
|
||||
if (a.size() != b.size())
|
||||
@@ -74,25 +75,25 @@ void fsc_reset()
|
||||
* /vol/content/data -> Map to HostFS
|
||||
* If overlapping paths with different priority are created, then the higher priority one will be checked first
|
||||
*/
|
||||
FSCMountPathNode* fsc_createMountPath(CoreinitFSParsedPath* parsedMountPath, sint32 priority)
|
||||
FSCMountPathNode* fsc_createMountPath(const FSCPath& mountPath, sint32 priority)
|
||||
{
|
||||
cemu_assert(priority >= 0 && priority < FSC_PRIORITY_COUNT);
|
||||
fscEnter();
|
||||
FSCMountPathNode* nodeParent = s_fscRootNodePerPrio[priority];
|
||||
for(sint32 i=0; i<parsedMountPath->numNodes; i++)
|
||||
for (size_t i=0; i< mountPath.GetNodeCount(); i++)
|
||||
{
|
||||
// search for subdirectory
|
||||
FSCMountPathNode* nodeSub = nullptr; // set if we found a subnode with a matching name, else this is used to store the new nodes
|
||||
for(auto& nodeItr : nodeParent->subnodes)
|
||||
for (auto& nodeItr : nodeParent->subnodes)
|
||||
{
|
||||
if( coreinitFS_checkNodeName(parsedMountPath, i, nodeItr->path.c_str()) )
|
||||
if (mountPath.MatchNodeName(i, nodeItr->path))
|
||||
{
|
||||
// subnode found
|
||||
nodeSub = nodeItr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( nodeSub )
|
||||
if (nodeSub)
|
||||
{
|
||||
// traverse subnode
|
||||
nodeParent = nodeSub;
|
||||
@@ -100,10 +101,10 @@ FSCMountPathNode* fsc_createMountPath(CoreinitFSParsedPath* parsedMountPath, sin
|
||||
}
|
||||
// no matching subnode, add new entry
|
||||
nodeSub = new FSCMountPathNode(nodeParent);
|
||||
nodeSub->path = coreinitFS_getNodeName(parsedMountPath, i);
|
||||
nodeSub->path = mountPath.GetNodeName(i);
|
||||
nodeSub->priority = priority;
|
||||
nodeParent->subnodes.emplace_back(nodeSub);
|
||||
if( i == (parsedMountPath->numNodes-1) )
|
||||
if (i == (mountPath.GetNodeCount() - 1))
|
||||
{
|
||||
// last node
|
||||
fscLeave();
|
||||
@@ -114,47 +115,44 @@ FSCMountPathNode* fsc_createMountPath(CoreinitFSParsedPath* parsedMountPath, sin
|
||||
}
|
||||
// path is empty or already mounted
|
||||
fscLeave();
|
||||
if (parsedMountPath->numNodes == 0)
|
||||
if (mountPath.GetNodeCount() == 0)
|
||||
return nodeParent;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Map a virtual FSC directory to a device and device directory
|
||||
sint32 fsc_mount(const char* mountPath, const wchar_t* _targetPath, fscDeviceC* fscDevice, void* ctx, sint32 priority)
|
||||
// Map a virtual FSC directory to a device. targetPath points to the destination base directory within the device
|
||||
sint32 fsc_mount(std::string_view mountPath, std::string_view targetPath, fscDeviceC* fscDevice, void* ctx, sint32 priority)
|
||||
{
|
||||
cemu_assert(fscDevice); // device must not be nullptr
|
||||
cemu_assert(fscDevice);
|
||||
std::string mountPathTmp(mountPath);
|
||||
// make sure the target path ends with a slash
|
||||
std::wstring targetPath(_targetPath);
|
||||
if (!targetPath.empty() && (targetPath.back() != '/' && targetPath.back() != '\\'))
|
||||
targetPath.push_back('/');
|
||||
std::string targetPathWithSlash(targetPath);
|
||||
if (!targetPathWithSlash.empty() && (targetPathWithSlash.back() != '/' && targetPathWithSlash.back() != '\\'))
|
||||
targetPathWithSlash.push_back('/');
|
||||
|
||||
// parse mount path
|
||||
CoreinitFSParsedPath parsedMountPath;
|
||||
coreinitFS_parsePath(&parsedMountPath, mountPath);
|
||||
FSCPath parsedMountPath(mountPathTmp);
|
||||
// register path
|
||||
fscEnter();
|
||||
FSCMountPathNode* node = fsc_createMountPath(&parsedMountPath, priority);
|
||||
FSCMountPathNode* node = fsc_createMountPath(parsedMountPath, priority);
|
||||
if( !node )
|
||||
{
|
||||
// path empty, invalid or already used
|
||||
cemuLog_log(LogType::Force, "fsc_mount failed (virtual path: %s)", mountPath);
|
||||
cemuLog_log(LogType::Force, "fsc_mount failed (virtual path: {})", mountPath);
|
||||
fscLeave();
|
||||
return FSC_STATUS_INVALID_PATH;
|
||||
}
|
||||
node->device = fscDevice;
|
||||
node->ctx = ctx;
|
||||
node->targetPath = targetPath;
|
||||
node->deviceTargetPath = targetPathWithSlash;
|
||||
fscLeave();
|
||||
return FSC_STATUS_OK;
|
||||
}
|
||||
|
||||
bool fsc_unmount(const char* mountPath, sint32 priority)
|
||||
bool fsc_unmount(std::string_view mountPath, sint32 priority)
|
||||
{
|
||||
CoreinitFSParsedPath parsedMountPath;
|
||||
coreinitFS_parsePath(&parsedMountPath, mountPath);
|
||||
|
||||
std::string _tmp(mountPath);
|
||||
fscEnter();
|
||||
FSCMountPathNode* mountPathNode = fsc_lookupPathVirtualNode(mountPath, priority);
|
||||
FSCMountPathNode* mountPathNode = fsc_lookupPathVirtualNode(_tmp.c_str(), priority);
|
||||
if (!mountPathNode)
|
||||
{
|
||||
fscLeave();
|
||||
@@ -185,21 +183,19 @@ void fsc_unmountAll()
|
||||
}
|
||||
|
||||
// lookup virtual path and find mounted device and relative device directory
|
||||
bool fsc_lookupPath(const char* path, std::wstring& devicePathOut, fscDeviceC** fscDeviceOut, void** ctxOut, sint32 priority = FSC_PRIORITY_BASE)
|
||||
bool fsc_lookupPath(const char* path, std::string& devicePathOut, fscDeviceC** fscDeviceOut, void** ctxOut, sint32 priority = FSC_PRIORITY_BASE)
|
||||
{
|
||||
// parse path
|
||||
CoreinitFSParsedPath parsedPath;
|
||||
coreinitFS_parsePath(&parsedPath, path);
|
||||
FSCPath parsedPath(path);
|
||||
FSCMountPathNode* nodeParent = s_fscRootNodePerPrio[priority];
|
||||
sint32 i;
|
||||
size_t i;
|
||||
fscEnter();
|
||||
for (i = 0; i < parsedPath.numNodes; i++)
|
||||
for (i = 0; i < parsedPath.GetNodeCount(); i++)
|
||||
{
|
||||
// search for subdirectory
|
||||
FSCMountPathNode* nodeSub = nullptr;
|
||||
for(auto& nodeItr : nodeParent->subnodes)
|
||||
{
|
||||
if (coreinitFS_checkNodeName(&parsedPath, i, nodeItr->path.c_str()))
|
||||
{
|
||||
if (parsedPath.MatchNodeName(i, nodeItr->path))
|
||||
{
|
||||
nodeSub = nodeItr;
|
||||
break;
|
||||
@@ -213,17 +209,17 @@ bool fsc_lookupPath(const char* path, std::wstring& devicePathOut, fscDeviceC**
|
||||
// no matching subnode
|
||||
break;
|
||||
}
|
||||
// find deepest device mount point
|
||||
// if the found node is not a device mount point, then travel back towards the root until we find one
|
||||
while (nodeParent)
|
||||
{
|
||||
if (nodeParent->device)
|
||||
{
|
||||
devicePathOut = nodeParent->targetPath;
|
||||
for (sint32 f = i; f < parsedPath.numNodes; f++)
|
||||
devicePathOut = nodeParent->deviceTargetPath;
|
||||
for (size_t f = i; f < parsedPath.GetNodeCount(); f++)
|
||||
{
|
||||
const char* nodeName = coreinitFS_getNodeName(&parsedPath, f);
|
||||
devicePathOut.append(boost::nowide::widen(nodeName));
|
||||
if (f < (parsedPath.numNodes - 1))
|
||||
auto nodeName = parsedPath.GetNodeName(f);
|
||||
devicePathOut.append(nodeName);
|
||||
if (f < (parsedPath.GetNodeCount() - 1))
|
||||
devicePathOut.push_back('/');
|
||||
}
|
||||
*fscDeviceOut = nodeParent->device;
|
||||
@@ -241,19 +237,16 @@ bool fsc_lookupPath(const char* path, std::wstring& devicePathOut, fscDeviceC**
|
||||
// lookup path and find virtual device node
|
||||
FSCMountPathNode* fsc_lookupPathVirtualNode(const char* path, sint32 priority)
|
||||
{
|
||||
// parse path
|
||||
CoreinitFSParsedPath parsedPath;
|
||||
coreinitFS_parsePath(&parsedPath, path);
|
||||
FSCPath parsedPath(path);
|
||||
FSCMountPathNode* nodeCurrentDir = s_fscRootNodePerPrio[priority];
|
||||
sint32 i;
|
||||
fscEnter();
|
||||
for (i = 0; i < parsedPath.numNodes; i++)
|
||||
for (size_t i = 0; i < parsedPath.GetNodeCount(); i++)
|
||||
{
|
||||
// search for subdirectory
|
||||
FSCMountPathNode* nodeSub = nullptr;
|
||||
for (auto& nodeItr : nodeCurrentDir->subnodes)
|
||||
{
|
||||
if (coreinitFS_checkNodeName(&parsedPath, i, nodeItr->path.c_str()))
|
||||
if (parsedPath.MatchNodeName(i, nodeItr->path))
|
||||
{
|
||||
nodeSub = nodeItr;
|
||||
break;
|
||||
@@ -360,11 +353,9 @@ private:
|
||||
FSCVirtualFile* fsc_open(const char* path, FSC_ACCESS_FLAG accessFlags, sint32* fscStatus, sint32 maxPriority)
|
||||
{
|
||||
cemu_assert_debug(HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE) || HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR)); // must open either file or directory
|
||||
|
||||
FSCVirtualFile* dirList[FSC_PRIORITY_COUNT];
|
||||
uint8 dirListCount = 0;
|
||||
|
||||
std::wstring devicePath;
|
||||
std::string devicePath;
|
||||
fscDeviceC* fscDevice = NULL;
|
||||
*fscStatus = FSC_STATUS_UNDEFINED;
|
||||
void* ctx;
|
||||
@@ -455,7 +446,7 @@ bool fsc_createDir(char* path, sint32* fscStatus)
|
||||
fscDeviceC* fscDevice = NULL;
|
||||
*fscStatus = FSC_STATUS_UNDEFINED;
|
||||
void* ctx;
|
||||
std::wstring devicePath;
|
||||
std::string devicePath;
|
||||
fscEnter();
|
||||
if( fsc_lookupPath(path, devicePath, &fscDevice, &ctx) )
|
||||
{
|
||||
@@ -472,8 +463,8 @@ bool fsc_createDir(char* path, sint32* fscStatus)
|
||||
*/
|
||||
bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus)
|
||||
{
|
||||
std::wstring srcDevicePath;
|
||||
std::wstring dstDevicePath;
|
||||
std::string srcDevicePath;
|
||||
std::string dstDevicePath;
|
||||
void* srcCtx;
|
||||
void* dstCtx;
|
||||
fscDeviceC* fscSrcDevice = NULL;
|
||||
@@ -492,7 +483,7 @@ bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus)
|
||||
*/
|
||||
bool fsc_remove(char* path, sint32* fscStatus)
|
||||
{
|
||||
std::wstring devicePath;
|
||||
std::string devicePath;
|
||||
fscDeviceC* fscDevice = NULL;
|
||||
*fscStatus = FSC_STATUS_UNDEFINED;
|
||||
void* ctx;
|
||||
@@ -691,7 +682,7 @@ bool fsc_doesFileExist(const char* path, sint32 maxPriority)
|
||||
return true;
|
||||
}
|
||||
|
||||
// helper function to check if a folder exists
|
||||
// helper function to check if a directory exists
|
||||
bool fsc_doesDirectoryExist(const char* path, sint32 maxPriority)
|
||||
{
|
||||
fscDeviceC* fscDevice = nullptr;
|
||||
@@ -708,93 +699,7 @@ bool fsc_doesDirectoryExist(const char* path, sint32 maxPriority)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void coreinitFS_parsePath(CoreinitFSParsedPath* parsedPath, const char* path)
|
||||
{
|
||||
// if the path starts with a '/', skip it
|
||||
if (*path == '/')
|
||||
path++;
|
||||
// init parsedPath struct
|
||||
memset(parsedPath, 0x00, sizeof(CoreinitFSParsedPath));
|
||||
// init parsed path data
|
||||
size_t pathLength = std::min((size_t)640, strlen(path));
|
||||
memcpy(parsedPath->pathData, path, pathLength);
|
||||
// start parsing
|
||||
sint32 offset = 0;
|
||||
sint32 startOffset = 0;
|
||||
if (offset < pathLength)
|
||||
{
|
||||
parsedPath->nodeOffset[parsedPath->numNodes] = offset;
|
||||
parsedPath->numNodes++;
|
||||
}
|
||||
while (offset < pathLength)
|
||||
{
|
||||
if (parsedPath->pathData[offset] == '/' || parsedPath->pathData[offset] == '\\')
|
||||
{
|
||||
parsedPath->pathData[offset] = '\0';
|
||||
offset++;
|
||||
// double slashes are ignored and instead are handled like a single slash
|
||||
if (parsedPath->pathData[offset] == '/' || parsedPath->pathData[offset] == '\\')
|
||||
{
|
||||
// if we're in the beginning and having a \\ it's a network path
|
||||
if (offset != 1)
|
||||
{
|
||||
parsedPath->pathData[offset] = '\0';
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
// start new node
|
||||
if (parsedPath->numNodes < FSC_PARSED_PATH_NODES_MAX)
|
||||
{
|
||||
if (offset < pathLength)
|
||||
{
|
||||
parsedPath->nodeOffset[parsedPath->numNodes] = offset;
|
||||
parsedPath->numNodes++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
// handle special nodes like '.' or '..'
|
||||
sint32 nodeIndex = 0;
|
||||
while (nodeIndex < parsedPath->numNodes)
|
||||
{
|
||||
if (coreinitFS_checkNodeName(parsedPath, nodeIndex, ".."))
|
||||
cemu_assert_suspicious(); // how does Cafe OS handle .. ?
|
||||
else if (coreinitFS_checkNodeName(parsedPath, nodeIndex, "."))
|
||||
{
|
||||
// remove this node and shift back all following nodes by 1
|
||||
parsedPath->numNodes--;
|
||||
for (sint32 i = nodeIndex; i < parsedPath->numNodes; i++)
|
||||
{
|
||||
parsedPath->nodeOffset[i] = parsedPath->nodeOffset[i + 1];
|
||||
}
|
||||
// continue without increasing nodeIndex
|
||||
continue;
|
||||
}
|
||||
nodeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
bool coreinitFS_checkNodeName(CoreinitFSParsedPath* parsedPath, sint32 index, const char* name)
|
||||
{
|
||||
if (index < 0 || index >= parsedPath->numNodes)
|
||||
return false;
|
||||
char* nodeName = parsedPath->pathData + parsedPath->nodeOffset[index];
|
||||
if (boost::iequals(nodeName, name))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
char* coreinitFS_getNodeName(CoreinitFSParsedPath* parsedPath, sint32 index)
|
||||
{
|
||||
if (index < 0 || index >= parsedPath->numNodes)
|
||||
return nullptr;
|
||||
return parsedPath->pathData + parsedPath->nodeOffset[index];
|
||||
}
|
||||
|
||||
// Initialize Cemu's virtual filesystem
|
||||
// initialize Cemu's virtual filesystem
|
||||
void fsc_init()
|
||||
{
|
||||
fsc_reset();
|
||||
|
||||
@@ -57,25 +57,25 @@ struct FSCDirEntry
|
||||
class fscDeviceC
|
||||
{
|
||||
public:
|
||||
virtual FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus)
|
||||
virtual FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus)
|
||||
{
|
||||
cemu_assert_unimplemented();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual bool fscDeviceCreateDir(std::wstring_view path, void* ctx, sint32* fscStatus)
|
||||
virtual bool fscDeviceCreateDir(std::string_view path, void* ctx, sint32* fscStatus)
|
||||
{
|
||||
cemu_assert_unimplemented();
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool fscDeviceRemoveFileOrDir(std::wstring_view path, void* ctx, sint32* fscStatus)
|
||||
virtual bool fscDeviceRemoveFileOrDir(std::string_view path, void* ctx, sint32* fscStatus)
|
||||
{
|
||||
cemu_assert_unimplemented();
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool fscDeviceRename(std::wstring_view srcPath, std::wstring_view dstPath, void* ctx, sint32* fscStatus)
|
||||
virtual bool fscDeviceRename(std::string_view srcPath, std::string_view dstPath, void* ctx, sint32* fscStatus)
|
||||
{
|
||||
cemu_assert_unimplemented();
|
||||
return false;
|
||||
@@ -161,8 +161,8 @@ struct FSCVirtualFile
|
||||
#define FSC_PRIORITY_COUNT (4)
|
||||
|
||||
void fsc_init();
|
||||
sint32 fsc_mount(const char* mountPath, const wchar_t* targetPath, fscDeviceC* fscDevice, void* ctx, sint32 priority=0);
|
||||
bool fsc_unmount(const char* mountPath, sint32 priority);
|
||||
sint32 fsc_mount(std::string_view mountPath, std::string_view targetPath, fscDeviceC* fscDevice, void* ctx, sint32 priority=0);
|
||||
bool fsc_unmount(std::string_view mountPath, sint32 priority);
|
||||
void fsc_unmountAll();
|
||||
|
||||
FSCVirtualFile* fsc_open(const char* path, FSC_ACCESS_FLAG accessFlags, sint32* fscStatus, sint32 maxPriority=FSC_PRIORITY_MAX);
|
||||
@@ -188,32 +188,15 @@ bool fsc_doesFileExist(const char* path, sint32 maxPriority = FSC_PRIORITY_MAX);
|
||||
bool fsc_doesDirectoryExist(const char* path, sint32 maxPriority = FSC_PRIORITY_MAX);
|
||||
|
||||
// wud device
|
||||
bool FSCDeviceWUD_Mount(const char* mountPath, std::string_view destinationBaseDir, class FSTVolume* mountedVolume, sint32 priority);
|
||||
bool FSCDeviceWUD_Mount(std::string_view mountPath, std::string_view destinationBaseDir, class FSTVolume* mountedVolume, sint32 priority);
|
||||
|
||||
// wua device
|
||||
bool FSCDeviceWUA_Mount(const char* mountPath, std::string_view destinationBaseDir, class ZArchiveReader* archive, sint32 priority);
|
||||
bool FSCDeviceWUA_Mount(std::string_view mountPath, std::string_view destinationBaseDir, class ZArchiveReader* archive, sint32 priority);
|
||||
|
||||
// hostFS device
|
||||
void fscDeviceHostFS_mapBaseDirectories_deprecated();
|
||||
bool FSCDeviceHostFS_Mount(const char* mountPath, const wchar_t* hostFSPath, sint32 priority);
|
||||
bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority);
|
||||
|
||||
// redirect device
|
||||
void fscDeviceRedirect_map();
|
||||
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority);
|
||||
|
||||
|
||||
// Old path parser helper functions
|
||||
// Replace with FSCPath
|
||||
|
||||
#define FSC_PARSED_PATH_NODES_MAX (32)
|
||||
|
||||
struct CoreinitFSParsedPath
|
||||
{
|
||||
char pathData[640 + 1];
|
||||
uint16 nodeOffset[FSC_PARSED_PATH_NODES_MAX];
|
||||
sint32 numNodes;
|
||||
};
|
||||
|
||||
void coreinitFS_parsePath(CoreinitFSParsedPath* parsedPath, const char* path);
|
||||
bool coreinitFS_checkNodeName(CoreinitFSParsedPath* parsedPath, sint32 index, const char* name);
|
||||
char* coreinitFS_getNodeName(CoreinitFSParsedPath* parsedPath, sint32 index);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "Cafe/Filesystem/fsc.h"
|
||||
#include "Cafe/Filesystem/fscDeviceHostFS.h"
|
||||
|
||||
#include "Common/filestream.h"
|
||||
#include "Common/FileStream.h"
|
||||
|
||||
/* FSCVirtualFile implementation for HostFS */
|
||||
|
||||
@@ -127,7 +127,7 @@ bool FSCVirtualFile_Host::fscDirNext(FSCDirEntry* dirEntry)
|
||||
m_dirIterator.reset(new fs::directory_iterator(*m_path));
|
||||
if (!m_dirIterator)
|
||||
{
|
||||
cemuLog_force("Failed to iterate directory: {}", _utf8Wrapper(m_path->generic_u8string()));
|
||||
cemuLog_force("Failed to iterate directory: {}", _pathToUtf8(*m_path));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -175,14 +175,14 @@ FSCVirtualFile* FSCVirtualFile_Host::OpenFile(const fs::path& path, FSC_ACCESS_F
|
||||
cemu_assert_debug(writeAccessRequested);
|
||||
fs = FileStream::createFile2(path);
|
||||
if (!fs)
|
||||
cemuLog_force("FSC: File create failed for {}", _utf8Wrapper(path));
|
||||
cemuLog_force("FSC: File create failed for {}", _pathToUtf8(path));
|
||||
}
|
||||
}
|
||||
else if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::FILE_ALWAYS_CREATE))
|
||||
{
|
||||
fs = FileStream::createFile2(path);
|
||||
if (!fs)
|
||||
cemuLog_force("FSC: File create failed for {}", _utf8Wrapper(path));
|
||||
cemuLog_force("FSC: File create failed for {}", _pathToUtf8(path));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -221,36 +221,36 @@ FSCVirtualFile* FSCVirtualFile_Host::OpenFile(const fs::path& path, FSC_ACCESS_F
|
||||
class fscDeviceHostFSC : public fscDeviceC
|
||||
{
|
||||
public:
|
||||
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_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
|
||||
{
|
||||
*fscStatus = FSC_STATUS_OK;
|
||||
FSCVirtualFile* vf = FSCVirtualFile_Host::OpenFile(path, accessFlags, *fscStatus);
|
||||
FSCVirtualFile* vf = FSCVirtualFile_Host::OpenFile(_utf8ToPath(path), accessFlags, *fscStatus);
|
||||
cemu_assert_debug((bool)vf == (*fscStatus == FSC_STATUS_OK));
|
||||
return vf;
|
||||
}
|
||||
|
||||
bool fscDeviceCreateDir(std::wstring_view path, void* ctx, sint32* fscStatus) override
|
||||
bool fscDeviceCreateDir(std::string_view path, void* ctx, sint32* fscStatus) override
|
||||
{
|
||||
fs::path dirPath(path);
|
||||
if (fs::exists(path))
|
||||
fs::path dirPath = _utf8ToPath(path);
|
||||
if (fs::exists(dirPath))
|
||||
{
|
||||
if (!fs::is_directory(dirPath))
|
||||
cemuLog_force("CreateDir: {} already exists but is not a directory", _utf8Wrapper(dirPath));
|
||||
cemuLog_force("CreateDir: {} already exists but is not a directory", path);
|
||||
*fscStatus = FSC_STATUS_ALREADY_EXISTS;
|
||||
return false;
|
||||
}
|
||||
std::error_code ec;
|
||||
bool r = fs::create_directories(dirPath, ec);
|
||||
if(!r)
|
||||
cemuLog_force("CreateDir: Failed to create {}", _utf8Wrapper(dirPath));
|
||||
if (!r)
|
||||
cemuLog_force("CreateDir: Failed to create {}", path);
|
||||
*fscStatus = FSC_STATUS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fscDeviceRemoveFileOrDir(std::wstring_view path, void* ctx, sint32* fscStatus) override
|
||||
bool fscDeviceRemoveFileOrDir(std::string_view path, void* ctx, sint32* fscStatus) override
|
||||
{
|
||||
*fscStatus = FSC_STATUS_OK;
|
||||
fs::path _path(path);
|
||||
fs::path _path = _utf8ToPath(path);
|
||||
std::error_code ec;
|
||||
if (!fs::exists(_path, ec))
|
||||
{
|
||||
@@ -266,11 +266,11 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fscDeviceRename(std::wstring_view srcPath, std::wstring_view dstPath, void* ctx, sint32* fscStatus) override
|
||||
bool fscDeviceRename(std::string_view srcPath, std::string_view dstPath, void* ctx, sint32* fscStatus) override
|
||||
{
|
||||
*fscStatus = FSC_STATUS_OK;
|
||||
fs::path _srcPath(srcPath);
|
||||
fs::path _dstPath(dstPath);
|
||||
fs::path _srcPath = _utf8ToPath(srcPath);
|
||||
fs::path _dstPath = _utf8ToPath(dstPath);
|
||||
std::error_code ec;
|
||||
if (!fs::exists(_srcPath, ec))
|
||||
{
|
||||
@@ -293,14 +293,11 @@ public:
|
||||
void fscDeviceHostFS_mapBaseDirectories_deprecated()
|
||||
{
|
||||
const auto mlc = ActiveSettings::GetMlcPath();
|
||||
fsc_mount("/cemuBossStorage/", (mlc / "usr/boss/").generic_wstring().c_str(), &fscDeviceHostFSC::instance(), NULL, FSC_PRIORITY_BASE);
|
||||
fsc_mount("/vol/storage_mlc01/", (mlc / "").generic_wstring().c_str(), &fscDeviceHostFSC::instance(), NULL, FSC_PRIORITY_BASE);
|
||||
fsc_mount("/cemuBossStorage/", _pathToUtf8(mlc / "usr/boss/"), &fscDeviceHostFSC::instance(), NULL, FSC_PRIORITY_BASE);
|
||||
fsc_mount("/vol/storage_mlc01/", _pathToUtf8(mlc / ""), &fscDeviceHostFSC::instance(), NULL, FSC_PRIORITY_BASE);
|
||||
}
|
||||
|
||||
bool FSCDeviceHostFS_Mount(const char* mountPath, const wchar_t* hostFSPath, sint32 priority)
|
||||
bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority)
|
||||
{
|
||||
std::wstring hostTargetPath(hostFSPath);
|
||||
if (!hostTargetPath.empty() && (hostTargetPath.back() != '/' && hostTargetPath.back() != '\\'))
|
||||
hostTargetPath.push_back('/');
|
||||
return fsc_mount(mountPath, hostTargetPath.c_str(), &fscDeviceHostFSC::instance(), nullptr, priority) == FSC_STATUS_OK;
|
||||
return fsc_mount(mountPath, hostTargetPath, &fscDeviceHostFSC::instance(), nullptr, priority) == FSC_STATUS_OK;
|
||||
}
|
||||
@@ -9,31 +9,30 @@ struct RedirectEntry
|
||||
sint32 priority;
|
||||
};
|
||||
|
||||
FileTree<RedirectEntry, false> redirectTree;
|
||||
FSAFileTree<RedirectEntry> redirectTree;
|
||||
|
||||
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority)
|
||||
{
|
||||
std::wstring virtualSourcePathW = boost::nowide::widen(std::string(virtualSourcePath));
|
||||
// check if source already has a redirection
|
||||
RedirectEntry* existingEntry;
|
||||
if (redirectTree.getFile(virtualSourcePathW, existingEntry))
|
||||
if (redirectTree.getFile(virtualSourcePath, existingEntry))
|
||||
{
|
||||
if (existingEntry->priority >= priority)
|
||||
return; // dont replace entries with equal or higher priority
|
||||
// unregister existing entry
|
||||
redirectTree.removeFile(virtualSourcePathW.c_str());
|
||||
redirectTree.removeFile(virtualSourcePath);
|
||||
delete existingEntry;
|
||||
}
|
||||
RedirectEntry* entry = new RedirectEntry(targetFilePath, priority);
|
||||
redirectTree.addFile(virtualSourcePathW.c_str(), entry);
|
||||
redirectTree.addFile(virtualSourcePath, entry);
|
||||
}
|
||||
|
||||
class fscDeviceTypeRedirect : public fscDeviceC
|
||||
{
|
||||
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view pathW, 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;
|
||||
if (redirectTree.getFile(pathW, redirectionEntry))
|
||||
if (redirectTree.getFile(path, redirectionEntry))
|
||||
return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -52,6 +51,6 @@ void fscDeviceRedirect_map()
|
||||
{
|
||||
if (_redirectMapped)
|
||||
return;
|
||||
fsc_mount("/", L"/", &fscDeviceTypeRedirect::instance(), nullptr, FSC_PRIORITY_REDIRECT);
|
||||
fsc_mount("/", "/", &fscDeviceTypeRedirect::instance(), nullptr, FSC_PRIORITY_REDIRECT);
|
||||
_redirectMapped = true;
|
||||
}
|
||||
|
||||
@@ -119,14 +119,12 @@ private:
|
||||
|
||||
class fscDeviceWUAC : public fscDeviceC
|
||||
{
|
||||
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_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
|
||||
{
|
||||
ZArchiveReader* archive = (ZArchiveReader*)ctx;
|
||||
cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to WUA is not supported
|
||||
|
||||
std::string pathU8 = boost::nowide::narrow(path.data(), path.size());
|
||||
|
||||
ZArchiveNodeHandle fileHandle = archive->LookUp(pathU8, true, true);
|
||||
ZArchiveNodeHandle fileHandle = archive->LookUp(path, true, true);
|
||||
if (fileHandle == ZARCHIVE_INVALID_NODE)
|
||||
{
|
||||
*fscStatus = FSC_STATUS_FILE_NOT_FOUND;
|
||||
@@ -169,10 +167,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool FSCDeviceWUA_Mount(const char* mountPath, std::string_view destinationBaseDir, ZArchiveReader* archive, sint32 priority)
|
||||
bool FSCDeviceWUA_Mount(std::string_view mountPath, std::string_view destinationBaseDir, ZArchiveReader* archive, sint32 priority)
|
||||
{
|
||||
std::wstring hostTargetPath(boost::nowide::widen(destinationBaseDir.data(), destinationBaseDir.size()));
|
||||
if (!hostTargetPath.empty() && (hostTargetPath.back() != '/' && hostTargetPath.back() != '\\'))
|
||||
hostTargetPath.push_back('/');
|
||||
return fsc_mount(mountPath, hostTargetPath.c_str(), &fscDeviceWUAC::instance(), archive, priority) == FSC_STATUS_OK;
|
||||
return fsc_mount(mountPath, destinationBaseDir, &fscDeviceWUAC::instance(), archive, priority) == FSC_STATUS_OK;
|
||||
}
|
||||
@@ -120,16 +120,15 @@ private:
|
||||
|
||||
class fscDeviceWUDC : public fscDeviceC
|
||||
{
|
||||
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_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
|
||||
{
|
||||
FSTVolume* mountedVolume = (FSTVolume*)ctx;
|
||||
cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to FST is never allowed
|
||||
|
||||
std::string pathU8 = boost::nowide::narrow(path.data(), path.size());
|
||||
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE))
|
||||
{
|
||||
FSTFileHandle fstFileHandle;
|
||||
if (mountedVolume->OpenFile(pathU8, fstFileHandle, true))
|
||||
if (mountedVolume->OpenFile(path, fstFileHandle, true))
|
||||
{
|
||||
*fscStatus = FSC_STATUS_OK;
|
||||
return new FSCDeviceWudFileCtx(mountedVolume, fstFileHandle);
|
||||
@@ -138,7 +137,7 @@ class fscDeviceWUDC : public fscDeviceC
|
||||
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR))
|
||||
{
|
||||
FSTDirectoryIterator dirIterator;
|
||||
if (mountedVolume->OpenDirectoryIterator(pathU8, dirIterator))
|
||||
if (mountedVolume->OpenDirectoryIterator(path, dirIterator))
|
||||
{
|
||||
*fscStatus = FSC_STATUS_OK;
|
||||
return new FSCDeviceWudFileCtx(mountedVolume, dirIterator);
|
||||
@@ -157,10 +156,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool FSCDeviceWUD_Mount(const char* mountPath, std::string_view destinationBaseDir, FSTVolume* mountedVolume, sint32 priority)
|
||||
bool FSCDeviceWUD_Mount(std::string_view mountPath, std::string_view destinationBaseDir, FSTVolume* mountedVolume, sint32 priority)
|
||||
{
|
||||
std::wstring hostTargetPath(boost::nowide::widen(destinationBaseDir.data(), destinationBaseDir.size()));
|
||||
if (!hostTargetPath.empty() && (hostTargetPath.back() != '/' && hostTargetPath.back() != '\\'))
|
||||
hostTargetPath.push_back('/');
|
||||
return fsc_mount(mountPath, hostTargetPath.c_str(), &fscDeviceWUDC::instance(), mountedVolume, priority) == FSC_STATUS_OK;
|
||||
return fsc_mount(mountPath, destinationBaseDir, &fscDeviceWUDC::instance(), mountedVolume, priority) == FSC_STATUS_OK;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user