From 06e92de8e500642be10cea6e5c638fb3525cc1a5 Mon Sep 17 00:00:00 2001 From: Maschell Date: Fri, 19 Feb 2021 20:32:44 +0100 Subject: [PATCH] Reimplement RPX/Bundle loading logic. --- src/FSFileReplacements.cpp | 12 +++--- src/FSWrapper.cpp | 42 ++++++++++---------- src/RPXLoading.cpp | 70 ++++++++++++++++++++------------- src/globals.cpp | 10 +---- src/globals.h | 36 ++++++++++++----- src/main.cpp | 80 +++++++++++++++++++------------------- 6 files changed, 138 insertions(+), 112 deletions(-) diff --git a/src/FSFileReplacements.cpp b/src/FSFileReplacements.cpp index 7cd5095..451e3ba 100644 --- a/src/FSFileReplacements.cpp +++ b/src/FSFileReplacements.cpp @@ -346,13 +346,13 @@ DECL_FUNCTION(FSStatus, FSGetFreeSpaceSizeAsync, FSClient *client, FSCmdBlock *b DECL_FUNCTION(FSStatus, FSChangeDirAsync, FSClient *client, FSCmdBlock *block, const char *path, FSErrorFlag errorMask, FSAsyncData *asyncData) { DEBUG_FUNCTION_LINE("FSChangeDirAsync %s", path); - strncpy(gWorkingDir, path, sizeof(gWorkingDir)); - int len = strlen(gWorkingDir); - if(len > 0 && gWorkingDir[len-1] != '/'){ - gWorkingDir[len-1] = '/'; - gWorkingDir[len] = 0; + strncpy(gReplacementInfo.bundleMountInformation.workingDir, path, sizeof(gReplacementInfo.bundleMountInformation.workingDir)); + int len = strlen(gReplacementInfo.bundleMountInformation.workingDir); + if(len > 0 && gReplacementInfo.bundleMountInformation.workingDir[len-1] != '/'){ + gReplacementInfo.bundleMountInformation.workingDir[len-1] = '/'; + gReplacementInfo.bundleMountInformation.workingDir[len] = 0; } - DCFlushRange(gWorkingDir, sizeof(gWorkingDir)); + DCFlushRange(gReplacementInfo.bundleMountInformation.workingDir, sizeof(gReplacementInfo.bundleMountInformation.workingDir)); return real_FSChangeDirAsync(client, block, path, errorMask, asyncData); } diff --git a/src/FSWrapper.cpp b/src/FSWrapper.cpp index fd5effc..66dede9 100644 --- a/src/FSWrapper.cpp +++ b/src/FSWrapper.cpp @@ -19,7 +19,7 @@ std::mutex file_handle_mutex; inline void getFullPath(char *pathForCheck, int pathSize, char *path) { if (path[0] != '/' && path[0] != '\\') { - snprintf(pathForCheck, pathSize, "%s%s", gWorkingDir, path); + snprintf(pathForCheck, pathSize, "%s%s", gReplacementInfo.bundleMountInformation.workingDir, path); DEBUG_FUNCTION_LINE_VERBOSE("Real path is %s", path); } else { strncpy(pathForCheck, path, pathSize - 1); @@ -33,7 +33,7 @@ inline bool checkForSave(char *pathForCheck, int pathSize, char *path) { memcpy(copy, path, copyLen); copy[copyLen] = 0; memset(pathForCheck,0, pathSize); - snprintf(pathForCheck, pathSize, "%s%s", gSavePath, ©[9]); + snprintf(pathForCheck, pathSize, "%s%s", gReplacementInfo.savePath, ©[9]); return true; } return false; @@ -127,7 +127,7 @@ FSStatus FSOpenDirWrapper(char *path, FSErrorFlag errorMask, std::function fallback_function, std::function result_handler) { - if (!gIsMounted) { + if (!gReplacementInfo.bundleMountInformation.isMounted) { return FS_STATUS_USE_REAL_OS; } @@ -183,7 +183,7 @@ FSStatus FSReadDirWrapper(FSDirectoryHandle handle, FSDirectoryEntry *entry, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidDirHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidDirHandle(handle)) { return FS_STATUS_USE_REAL_OS; } @@ -231,7 +231,7 @@ FSStatus FSReadDirWrapper(FSDirectoryHandle handle, FSStatus FSCloseDirWrapper(FSDirectoryHandle handle, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidDirHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidDirHandle(handle)) { return FS_STATUS_USE_REAL_OS; } uint32_t handle_index = handle & HANDLE_MASK; @@ -257,7 +257,7 @@ FSStatus FSCloseDirWrapper(FSDirectoryHandle handle, FSStatus FSRewindDirWrapper(FSDirectoryHandle handle, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidDirHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidDirHandle(handle)) { return FS_STATUS_USE_REAL_OS; } uint32_t handle_index = handle & HANDLE_MASK; @@ -278,7 +278,7 @@ FSStatus FSMakeDirWrapper(char *path, FSErrorFlag errorMask, std::function fallback_function, std::function result_handler) { - if (!gIsMounted) { + if (!gReplacementInfo.bundleMountInformation.isMounted) { return FS_STATUS_USE_REAL_OS; } @@ -307,7 +307,7 @@ FSStatus FSOpenFileWrapper(char *path, FSErrorFlag errorMask, std::function fallback_function, std::function result_handler) { - if (!gIsMounted) { + if (!gReplacementInfo.bundleMountInformation.isMounted) { return FS_STATUS_USE_REAL_OS; } if (path == nullptr) { @@ -386,7 +386,7 @@ FSStatus FSOpenFileWrapper(char *path, FSStatus FSCloseFileWrapper(FSFileHandle handle, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } @@ -417,7 +417,7 @@ FSStatus FSCloseFileWrapper(FSFileHandle handle, FSStatus FSGetStatWrapper(char *path, FSStat *stats, FSErrorFlag errorMask, std::function fallback_function, std::function result_handler) { - if (!gIsMounted) { + if (!gReplacementInfo.bundleMountInformation.isMounted) { return FS_STATUS_USE_REAL_OS; } if (path == nullptr) { @@ -470,7 +470,7 @@ FSStatus FSGetStatFileWrapper(FSFileHandle handle, FSStat *stats, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } uint32_t handle_index = handle & HANDLE_MASK; @@ -511,7 +511,7 @@ FSStatus FSReadFileWrapper(void *buffer, uint32_t unk1, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } uint32_t handle_index = handle & HANDLE_MASK; @@ -556,7 +556,7 @@ FSStatus FSReadFileWithPosWrapper(void *buffer, int32_t unk1, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } FSStatus result; @@ -579,7 +579,7 @@ FSStatus FSSetPosFileWrapper(FSFileHandle handle, uint32_t pos, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } @@ -609,7 +609,7 @@ FSStatus FSGetPosFileWrapper(FSFileHandle handle, uint32_t *pos, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } uint32_t handle_index = handle & HANDLE_MASK; @@ -640,7 +640,7 @@ FSStatus FSGetPosFileWrapper(FSFileHandle handle, FSStatus FSIsEofWrapper(FSFileHandle handle, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } uint32_t handle_index = handle & HANDLE_MASK; @@ -674,7 +674,7 @@ FSStatus FSIsEofWrapper(FSFileHandle handle, FSStatus FSTruncateFileWrapper(FSFileHandle handle, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } uint32_t handle_index = handle & HANDLE_MASK; @@ -697,7 +697,7 @@ FSStatus FSWriteFileWrapper(uint8_t *buffer, uint32_t unk1, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } FSStatus result = FS_STATUS_OK; @@ -711,7 +711,7 @@ FSStatus FSRemoveWrapper(char *path, FSErrorFlag errorMask, std::function fallback_function, std::function result_handler) { - if (!gIsMounted) { + if (!gReplacementInfo.bundleMountInformation.isMounted) { return FS_STATUS_USE_REAL_OS; } @@ -740,7 +740,7 @@ FSStatus FSRenameWrapper(char *oldPath, FSErrorFlag errorMask, std::function fallback_function, std::function result_handler) { - if (!gIsMounted) { + if (!gReplacementInfo.bundleMountInformation.isMounted) { return FS_STATUS_USE_REAL_OS; } @@ -767,7 +767,7 @@ FSStatus FSRenameWrapper(char *oldPath, } FSStatus FSFlushFileWrapper(FSFileHandle handle, FSErrorFlag errorMask, std::function result_handler) { - if (!gIsMounted || !isValidFileHandle(handle)) { + if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) { return FS_STATUS_USE_REAL_OS; } FSStatus result = FS_STATUS_OK; diff --git a/src/RPXLoading.cpp b/src/RPXLoading.cpp index d4f8b10..9adeadb 100644 --- a/src/RPXLoading.cpp +++ b/src/RPXLoading.cpp @@ -16,17 +16,16 @@ #include #include -char gIconCache[65580] __attribute__((section(".data"))); /* * Patch the meta xml for the home menu */ DECL_FUNCTION(int32_t, HBM_NN_ACP_ACPGetTitleMetaXmlByDevice, uint32_t titleid_upper, uint32_t titleid_lower, ACPMetaXml *metaxml, uint32_t device) { - if (gReplacedRPX) { + if (gReplacementInfo.isRPXReplaced) { memset(&metaxml->longname_ja, 0, 0x338C - 0x38C); // clear all names - strncpy(metaxml->longname_en, gBundleInfo.longname, sizeof(gBundleInfo.longname)); - strncpy(metaxml->shortname_en, gBundleInfo.shortname, sizeof(gBundleInfo.longname)); - strncpy(metaxml->publisher_en, gBundleInfo.author, sizeof(gBundleInfo.longname)); + strncpy(metaxml->longname_en, gReplacementInfo.metaInformation.longname, sizeof(gReplacementInfo.metaInformation.longname)); + strncpy(metaxml->shortname_en, gReplacementInfo.metaInformation.shortname, sizeof(gReplacementInfo.metaInformation.shortname)); + strncpy(metaxml->publisher_en, gReplacementInfo.metaInformation.author, sizeof(gReplacementInfo.metaInformation.author)); // Disbale the emanual metaxml->e_manual = 0; @@ -40,9 +39,9 @@ DECL_FUNCTION(int32_t, HBM_NN_ACP_ACPGetTitleMetaXmlByDevice, uint32_t titleid_u DECL_FUNCTION(int, RPX_FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, const char *mode, int *handle, int error) { const char *iconTex = "iconTex.tga"; if (StringTools::EndsWith(path, iconTex)) { - if (gReplacedRPX) { + if (gReplacementInfo.isRPXReplaced) { if (StringTools::EndsWith(path, iconTex)) { - auto *reader = new FileReader(reinterpret_cast(gIconCache), sizeof(gIconCache)); + auto *reader = new FileReader(reinterpret_cast(gReplacementInfo.iconCache), sizeof(gReplacementInfo.iconCache)); *handle = (uint32_t) reader; return FS_STATUS_OK; } @@ -85,7 +84,7 @@ uint32_t rpx_utils_function_replacements_size = sizeof(rpx_utils_function_replac static int parseINIhandler(void *user, const char *section, const char *name, const char *value) { - auto *fInfo = (BundleInformation *) user; + auto *fInfo = (MetaInformation *) user; #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 if (MATCH("menu", "longname")) { strncpy(fInfo->longname, value, 64 - 1); @@ -113,16 +112,19 @@ bool RL_LoadFromSDOnNextLaunch(const char *bundle_path) { bool metaLoaded = false; + gReplacementInfo.replacementType = RPXLoader_RPX; + std::string completePath = std::string("/vol/external01/") + bundle_path; int res = getRPXInfoForPath(completePath, &info); bool isBundle = false; if (res >= 0) { + gReplacementInfo.replacementType = RPXLoader_BUNDLE; isBundle = true; request.filesize = ((uint32_t *) &info.length)[1]; request.fileoffset = ((uint32_t *) &info.offset)[1]; if (romfsMount("rcc", completePath.c_str(), RomfsSource_FileDescriptor_CafeOS) == 0) { - if (ini_parse("rcc:/meta/meta.ini", parseINIhandler, &gBundleInfo) < 0) { + if (ini_parse("rcc:/meta/meta.ini", parseINIhandler, &gReplacementInfo.metaInformation) < 0) { DEBUG_FUNCTION_LINE("Failed to load and parse meta.ini"); } else { metaLoaded = true; @@ -138,60 +140,74 @@ bool RL_LoadFromSDOnNextLaunch(const char *bundle_path) { } if (reader) { uint32_t alreadyRead = 0; - uint32_t toRead = sizeof(gIconCache); + uint32_t toRead = sizeof(gReplacementInfo.iconCache); do { - int read = reader->read(reinterpret_cast(&gIconCache[alreadyRead]), toRead); + int read = reader->read(reinterpret_cast(&gReplacementInfo.iconCache[alreadyRead]), toRead); if (read <= 0) { break; } alreadyRead += read; toRead -= read; - } while (alreadyRead < sizeof(gIconCache)); + } while (alreadyRead < sizeof(gReplacementInfo.iconCache)); delete reader; } else { - memset(gIconCache, 0, sizeof(gIconCache)); + memset(gReplacementInfo.iconCache, 0, sizeof(gReplacementInfo.iconCache)); } romfsUnmount("rcc"); } } if (!metaLoaded) { - strncpy(gBundleInfo.author, bundle_path, 64 - 1); - strncpy(gBundleInfo.shortname, bundle_path, 64 - 1); - strncpy(gBundleInfo.longname, bundle_path, 64 - 1); + strncpy(gReplacementInfo.metaInformation.author, bundle_path, sizeof(gReplacementInfo.metaInformation.author)); + strncpy(gReplacementInfo.metaInformation.shortname, bundle_path, sizeof(gReplacementInfo.metaInformation.shortname)); + strncpy(gReplacementInfo.metaInformation.longname, bundle_path, sizeof(gReplacementInfo.metaInformation.longname)); } strncpy(request.path, bundle_path, 255); - DEBUG_FUNCTION_LINE("Launch %s on next restart [size: %08X offset: %08X]", request.path, request.filesize, request.fileoffset); - - DCFlushRange(gIconCache, sizeof(gIconCache)); DCFlushRange(&request, sizeof(LOAD_REQUEST)); - DCFlushRange(&gBundleInfo, sizeof(gBundleInfo)); + int success = false; int mcpFd = IOS_Open("/dev/mcp", (IOSOpenMode) 0); if (mcpFd >= 0) { int out = 0; IOS_Ioctl(mcpFd, 100, &request, sizeof(request), &out, sizeof(out)); + if (out > 0) { + success = true; + } + IOS_Close(mcpFd); } + DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo)); + + if (!success) { + gReplacementInfo.replacementType = RPXLoader_NONE; + DEBUG_FUNCTION_LINE("Failed to load %s on next restart", request.path); + return false; + } + + DEBUG_FUNCTION_LINE("Launch %s on next restart [size: %08X offset: %08X]", request.path, request.filesize, request.fileoffset); + if (isBundle) { DEBUG_FUNCTION_LINE("Loaded file is a .wuhb bundle"); - gTryToReplaceOnNextLaunch = true; - memset(gLoadedBundlePath, 0, sizeof(gLoadedBundlePath)); - strncpy(gLoadedBundlePath, completePath.c_str(), completePath.length()); + memset(gReplacementInfo.bundleMountInformation.path, 0, sizeof(gReplacementInfo.bundleMountInformation.path)); + strncpy(gReplacementInfo.bundleMountInformation.path, completePath.c_str(), completePath.length()); + gReplacementInfo.replacementType = RPXLoader_BUNDLE; + gReplacementInfo.bundleMountInformation.redirectionRequested = true; } else { DEBUG_FUNCTION_LINE("Loaded file is no bundle"); - if (!gIsMounted) { - gTryToReplaceOnNextLaunch = false; - memset(gLoadedBundlePath, 0, sizeof(gLoadedBundlePath)); + if (!gReplacementInfo.bundleMountInformation.isMounted) { + memset(gReplacementInfo.bundleMountInformation.path, 0, sizeof(gReplacementInfo.bundleMountInformation.path)); } else { + gReplacementInfo.replacementType = RPXLoader_BUNDLE_OTHER_RPX; + gReplacementInfo.bundleMountInformation.redirectionRequested = true; // keep the old /vol/content mounted, this way you can reload just the rpx via wiiload - gTryToReplaceOnNextLaunch = true; } } + DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo)); + return true; } diff --git a/src/globals.cpp b/src/globals.cpp index f902dc5..7457504 100644 --- a/src/globals.cpp +++ b/src/globals.cpp @@ -1,11 +1,3 @@ #include "globals.h" -bool gIsMounted __attribute__((section(".data"))) = false; -uint32_t gCurrentHash __attribute__((section(".data"))) = 0; -bool gTryToReplaceOnNextLaunch __attribute__((section(".data"))) = false; -char gLoadedBundlePath[256] __attribute__((section(".data"))); -char gSavePath[256] __attribute__((section(".data"))); -char gWorkingDir[256] __attribute__((section(".data"))); - -bool gReplacedRPX __attribute__((section(".data"))) = false; -BundleInformation gBundleInfo __attribute__((section(".data"))); \ No newline at end of file +RPXLoader_ReplacementInformation gReplacementInfo __attribute__((section(".data"))); \ No newline at end of file diff --git a/src/globals.h b/src/globals.h index 3443f8b..ac78f39 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1,18 +1,34 @@ #include #include -typedef struct BundleInformation_t { +typedef struct MetaInformation_t { char shortname[64]; char longname[64]; char author[64]; -} BundleInformation; +} MetaInformation; +typedef struct BundleMountInformation_t { + bool redirectionRequested; + bool isMounted; + char path[255]; + char workingDir[255]; +} BundleMountInformation; -extern bool gIsMounted; -extern bool gTryToReplaceOnNextLaunch; -extern char gLoadedBundlePath[256]; -extern char gSavePath[256]; -extern char gWorkingDir[256]; -extern uint32_t gCurrentHash; -extern bool gReplacedRPX; -extern BundleInformation gBundleInfo; \ No newline at end of file +typedef enum RPXLoader_Type { + RPXLoader_NONE, + RPXLoader_RPX, + RPXLoader_BUNDLE, + RPXLoader_BUNDLE_OTHER_RPX, +} RPXLoader_Type; + +typedef struct RPXLoader_ReplacementInformation_t { + bool isRPXReplaced; + MetaInformation metaInformation; + RPXLoader_Type replacementType; + BundleMountInformation bundleMountInformation; + char iconCache[65580]; + uint32_t currentHash; + char savePath[255]; +} RPXLoader_ReplacementInformation; + +extern RPXLoader_ReplacementInformation gReplacementInfo; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index bb223e7..a88b937 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,16 +27,16 @@ WUMS_INITIALIZE() { FunctionPatcherPatchFunction(fs_dir_function_replacements, fs_dir_function_replacements_size); FunctionPatcherPatchFunction(rpx_utils_function_replacements, rpx_utils_function_replacements_size); DEBUG_FUNCTION_LINE("Patch functions finished"); - gIsMounted = false; + gReplacementInfo = {}; } WUMS_APPLICATION_ENDS() { - if (gIsMounted) { + if (gReplacementInfo.bundleMountInformation.isMounted) { DEBUG_FUNCTION_LINE("Unmount /vol/content"); romfsUnmount("rom"); - gIsMounted = false; - DCFlushRange(&gIsMounted, sizeof(gIsMounted)); + gReplacementInfo.bundleMountInformation.isMounted = false; + DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo)); } } @@ -48,43 +48,45 @@ WUMS_APPLICATION_STARTS() { WHBLogUdpInit(); if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) != OSGetTitleID()) { DEBUG_FUNCTION_LINE("Set gTryToReplaceOnNextLaunch, gReplacedRPX and gIsMounted to FALSE"); - gReplacedRPX = false; - gTryToReplaceOnNextLaunch = false; - gIsMounted = false; - DCFlushRange(&gReplacedRPX, sizeof(gReplacedRPX)); - DCFlushRange(&gTryToReplaceOnNextLaunch, sizeof(gTryToReplaceOnNextLaunch)); - DCFlushRange(&gIsMounted, sizeof(gIsMounted)); + gReplacementInfo.replacementType = RPXLoader_NONE; + gReplacementInfo.isRPXReplaced = false; + gReplacementInfo.bundleMountInformation.isMounted = false; + gReplacementInfo.bundleMountInformation.redirectionRequested = false; + DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo)); } else { - if (gTryToReplaceOnNextLaunch) { - gCurrentHash = StringTools::hash(gLoadedBundlePath); - - nn::act::Initialize(); - nn::act::SlotNo slot = nn::act::GetSlotNo(); - nn::act::Finalize(); - - std::string basePath = StringTools::strfmt("/vol/external01/wiiu/apps/save/%08X", gCurrentHash); - std::string common = StringTools::strfmt("fs:/vol/external01/wiiu/apps/save/%08X/common", gCurrentHash); - std::string user = StringTools::strfmt("fs:/vol/external01/wiiu/apps/save/%08X/%08X", gCurrentHash, 0x80000000 | slot); - - strncpy(gSavePath,basePath.c_str(), 255); - memset(gWorkingDir, 0, sizeof(gWorkingDir)); - DCFlushRange(gWorkingDir, sizeof(gWorkingDir)); - - CreateSubfolder(common.c_str()); - CreateSubfolder(user.c_str()); - DEBUG_FUNCTION_LINE("Created %s and %s", common.c_str(), user.c_str()); - if (romfsMount("rom", gLoadedBundlePath, RomfsSource_FileDescriptor_CafeOS) == 0) { - DEBUG_FUNCTION_LINE("Mounted %s to /vol/content", gLoadedBundlePath); - gIsMounted = true; - } else { - DEBUG_FUNCTION_LINE("Failed to mount %s", gLoadedBundlePath); - gIsMounted = false; - } - gReplacedRPX = true; - DCFlushRange(&gReplacedRPX, sizeof(gReplacedRPX)); - DCFlushRange(&gIsMounted, sizeof(gIsMounted)); - DCFlushRange(&gTryToReplaceOnNextLaunch, sizeof(gTryToReplaceOnNextLaunch)); + if (gReplacementInfo.replacementType != RPXLoader_NONE) { + gReplacementInfo.isRPXReplaced = true; } + if (gReplacementInfo.bundleMountInformation.redirectionRequested) { + if (gReplacementInfo.replacementType == RPXLoader_BUNDLE || gReplacementInfo.replacementType == RPXLoader_BUNDLE_OTHER_RPX) { + gReplacementInfo.currentHash = StringTools::hash(gReplacementInfo.bundleMountInformation.path); + + nn::act::Initialize(); + nn::act::SlotNo slot = nn::act::GetSlotNo(); + nn::act::Finalize(); + + std::string basePath = StringTools::strfmt("/vol/external01/wiiu/apps/save/%08X", gReplacementInfo.currentHash); + std::string common = StringTools::strfmt("fs:/vol/external01/wiiu/apps/save/%08X/common", gReplacementInfo.currentHash); + std::string user = StringTools::strfmt("fs:/vol/external01/wiiu/apps/save/%08X/%08X", gReplacementInfo.currentHash, 0x80000000 | slot); + + strncpy(gReplacementInfo.savePath, basePath.c_str(), sizeof(gReplacementInfo.savePath)); + memset(gReplacementInfo.bundleMountInformation.workingDir, 0, sizeof(gReplacementInfo.bundleMountInformation.workingDir)); + + CreateSubfolder(common.c_str()); + CreateSubfolder(user.c_str()); + DEBUG_FUNCTION_LINE("Created %s and %s", common.c_str(), user.c_str()); + if (romfsMount("rom", gReplacementInfo.bundleMountInformation.path, RomfsSource_FileDescriptor_CafeOS) == 0) { + DEBUG_FUNCTION_LINE("Mounted %s to /vol/content", gReplacementInfo.bundleMountInformation.path); + gReplacementInfo.bundleMountInformation.isMounted = true; + } else { + DEBUG_FUNCTION_LINE("Failed to mount %s", gReplacementInfo.bundleMountInformation.path); + gReplacementInfo.bundleMountInformation.isMounted = false; + } + } else if (gReplacementInfo.replacementType == RPXLoader_RPX) { + // + } + } + DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo)); } }