mirror of
https://github.com/wiiu-env/RPXLoadingModule.git
synced 2024-11-29 05:14:14 +01:00
Refactor content redirection
This commit is contained in:
parent
5f1b0bf67e
commit
2e25fbd8c1
@ -1,5 +1,6 @@
|
|||||||
#include "FSDirReplacements.h"
|
#include "FSDirReplacements.h"
|
||||||
#include <coreinit/filesystem.h>
|
#include <coreinit/filesystem.h>
|
||||||
|
#include <coreinit/cache.h>
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "FSWrapper.h"
|
#include "FSWrapper.h"
|
||||||
@ -134,6 +135,18 @@ DECL_FUNCTION(FSStatus, FSMakeDirAsync, FSClient *client, FSCmdBlock *block, cha
|
|||||||
return real_FSMakeDirAsync(client, block, path, errorMask, asyncData);
|
return real_FSMakeDirAsync(client, block, path, errorMask, asyncData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECL_FUNCTION(FSStatus, FSChangeDirAsync, FSClient *client, FSCmdBlock *block, const char *path, FSErrorFlag errorMask, FSAsyncData *asyncData) {
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("FSChangeDirAsync %s", path);
|
||||||
|
snprintf(gReplacementInfo.contentReplacementInfo.workingDir, sizeof(gReplacementInfo.contentReplacementInfo.workingDir), "%s", path);
|
||||||
|
int len = strlen(gReplacementInfo.contentReplacementInfo.workingDir);
|
||||||
|
if (len > 0 && gReplacementInfo.contentReplacementInfo.workingDir[len - 1] != '/') {
|
||||||
|
gReplacementInfo.contentReplacementInfo.workingDir[len - 1] = '/';
|
||||||
|
gReplacementInfo.contentReplacementInfo.workingDir[len] = 0;
|
||||||
|
}
|
||||||
|
DCFlushRange(gReplacementInfo.contentReplacementInfo.workingDir, sizeof(gReplacementInfo.contentReplacementInfo.workingDir));
|
||||||
|
return real_FSChangeDirAsync(client, block, path, errorMask, asyncData);
|
||||||
|
}
|
||||||
|
|
||||||
function_replacement_data_t fs_dir_function_replacements[] = {
|
function_replacement_data_t fs_dir_function_replacements[] = {
|
||||||
REPLACE_FUNCTION(FSOpenDir, LIBRARY_COREINIT, FSOpenDir),
|
REPLACE_FUNCTION(FSOpenDir, LIBRARY_COREINIT, FSOpenDir),
|
||||||
REPLACE_FUNCTION(FSOpenDirAsync, LIBRARY_COREINIT, FSOpenDirAsync),
|
REPLACE_FUNCTION(FSOpenDirAsync, LIBRARY_COREINIT, FSOpenDirAsync),
|
||||||
@ -149,6 +162,8 @@ function_replacement_data_t fs_dir_function_replacements[] = {
|
|||||||
|
|
||||||
REPLACE_FUNCTION(FSMakeDir, LIBRARY_COREINIT, FSMakeDir),
|
REPLACE_FUNCTION(FSMakeDir, LIBRARY_COREINIT, FSMakeDir),
|
||||||
REPLACE_FUNCTION(FSMakeDirAsync, LIBRARY_COREINIT, FSMakeDirAsync),
|
REPLACE_FUNCTION(FSMakeDirAsync, LIBRARY_COREINIT, FSMakeDirAsync),
|
||||||
|
|
||||||
|
REPLACE_FUNCTION(FSChangeDirAsync, LIBRARY_COREINIT, FSChangeDirAsync),
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t fs_dir_function_replacements_size = sizeof(fs_dir_function_replacements) / sizeof(function_replacement_data_t);
|
uint32_t fs_dir_function_replacements_size = sizeof(fs_dir_function_replacements) / sizeof(function_replacement_data_t);
|
@ -344,17 +344,6 @@ DECL_FUNCTION(FSStatus, FSGetFreeSpaceSizeAsync, FSClient *client, FSCmdBlock *b
|
|||||||
return real_FSGetFreeSpaceSizeAsync(client, block, path, outSize, errorMask, asyncData);
|
return real_FSGetFreeSpaceSizeAsync(client, block, path, outSize, errorMask, asyncData);
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_FUNCTION(FSStatus, FSChangeDirAsync, FSClient *client, FSCmdBlock *block, const char *path, FSErrorFlag errorMask, FSAsyncData *asyncData) {
|
|
||||||
DEBUG_FUNCTION_LINE("FSChangeDirAsync %s", path);
|
|
||||||
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(gReplacementInfo.bundleMountInformation.workingDir, sizeof(gReplacementInfo.bundleMountInformation.workingDir));
|
|
||||||
return real_FSChangeDirAsync(client, block, path, errorMask, asyncData);
|
|
||||||
}
|
|
||||||
|
|
||||||
function_replacement_data_t fs_file_function_replacements[] = {
|
function_replacement_data_t fs_file_function_replacements[] = {
|
||||||
REPLACE_FUNCTION(FSOpenFile, LIBRARY_COREINIT, FSOpenFile),
|
REPLACE_FUNCTION(FSOpenFile, LIBRARY_COREINIT, FSOpenFile),
|
||||||
@ -399,8 +388,6 @@ function_replacement_data_t fs_file_function_replacements[] = {
|
|||||||
REPLACE_FUNCTION(FSFlushFile, LIBRARY_COREINIT, FSFlushFile),
|
REPLACE_FUNCTION(FSFlushFile, LIBRARY_COREINIT, FSFlushFile),
|
||||||
REPLACE_FUNCTION(FSFlushFileAsync, LIBRARY_COREINIT, FSFlushFileAsync),
|
REPLACE_FUNCTION(FSFlushFileAsync, LIBRARY_COREINIT, FSFlushFileAsync),
|
||||||
|
|
||||||
REPLACE_FUNCTION(FSChangeDirAsync, LIBRARY_COREINIT, FSChangeDirAsync),
|
|
||||||
|
|
||||||
//REPLACE_FUNCTION(FSChangeModeAsync, LIBRARY_COREINIT, FSChangeModeAsync),
|
//REPLACE_FUNCTION(FSChangeModeAsync, LIBRARY_COREINIT, FSChangeModeAsync),
|
||||||
|
|
||||||
//REPLACE_FUNCTION(FSGetFreeSpaceSizeAsync, LIBRARY_COREINIT, FSGetFreeSpaceSizeAsync),
|
//REPLACE_FUNCTION(FSGetFreeSpaceSizeAsync, LIBRARY_COREINIT, FSGetFreeSpaceSizeAsync),
|
||||||
|
@ -17,23 +17,32 @@ fileMagic_t file_handles[FILE_HANDLES_LENGTH];
|
|||||||
std::mutex dir_handle_mutex;
|
std::mutex dir_handle_mutex;
|
||||||
std::mutex file_handle_mutex;
|
std::mutex file_handle_mutex;
|
||||||
|
|
||||||
|
static inline void replaceContentPath(char *pathForCheck, int pathForCheckSize, int replaceLen, char *replaceWith);
|
||||||
|
|
||||||
inline void getFullPath(char *pathForCheck, int pathSize, char *path) {
|
inline void getFullPath(char *pathForCheck, int pathSize, char *path) {
|
||||||
if (path[0] != '/' && path[0] != '\\') {
|
if (path[0] != '/' && path[0] != '\\') {
|
||||||
snprintf(pathForCheck, pathSize, "%s%s", gReplacementInfo.bundleMountInformation.workingDir, path);
|
snprintf(pathForCheck, pathSize, "%s%s", gReplacementInfo.contentReplacementInfo.workingDir, path);
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Real path is %s", path);
|
DEBUG_FUNCTION_LINE_VERBOSE("Real path is %s", path);
|
||||||
} else {
|
} else {
|
||||||
strncpy(pathForCheck, path, pathSize - 1);
|
pathForCheck[0] = '\0';
|
||||||
|
strncat(pathForCheck, path, pathSize - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < strlen(pathForCheck);i++){
|
||||||
|
if(pathForCheck[i] == '\\'){
|
||||||
|
pathForCheck[i] = '/';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool checkForSave(char *pathForCheck, int pathSize, char *path) {
|
inline bool checkForSave(char *pathForCheck, int pathSize, char *path) {
|
||||||
if (strncmp(path, "/vol/save", 9) == 0) {
|
if (strncmp(path, "/vol/save", 9) == 0) {
|
||||||
int copyLen = strlen(path);
|
int copyLen = strlen(path);
|
||||||
char copy[copyLen+1];
|
char copy[copyLen + 1];
|
||||||
memcpy(copy, path, copyLen);
|
memcpy(copy, path, copyLen);
|
||||||
copy[copyLen] = 0;
|
copy[copyLen] = 0;
|
||||||
memset(pathForCheck,0, pathSize);
|
memset(pathForCheck, 0, pathSize);
|
||||||
snprintf(pathForCheck, pathSize, "%s%s", gReplacementInfo.savePath, ©[9]);
|
snprintf(pathForCheck, pathSize, "%s%s", gReplacementInfo.contentReplacementInfo.savePath, ©[9]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -127,7 +136,8 @@ FSStatus FSOpenDirWrapper(char *path,
|
|||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(char *_path)> fallback_function,
|
std::function<FSStatus(char *_path)> fallback_function,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,9 +155,9 @@ FSStatus FSOpenDirWrapper(char *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(pathForCheck, "/vol/content", 12) == 0) {
|
if (strncmp(pathForCheck, "/vol/content", 12) == 0) {
|
||||||
memcpy(pathForCheck, "rom:", 4);
|
replaceContentPath(pathForCheck, sizeof(pathForCheck), 12, gReplacementInfo.contentReplacementInfo.replacementPath);
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("%s", path);
|
DEBUG_FUNCTION_LINE_VERBOSE("%s -> %s", path, pathForCheck);
|
||||||
FSStatus result = FS_STATUS_OK;
|
FSStatus result = FS_STATUS_OK;
|
||||||
|
|
||||||
int handle_index = getNewDirHandleIndex();
|
int handle_index = getNewDirHandleIndex();
|
||||||
@ -160,11 +170,17 @@ FSStatus FSOpenDirWrapper(char *path,
|
|||||||
*handle = dir_handles[handle_index].handle;
|
*handle = dir_handles[handle_index].handle;
|
||||||
dir_handles[handle_index].dir = dir;
|
dir_handles[handle_index].dir = dir;
|
||||||
dir_handles[handle_index].in_use = true;
|
dir_handles[handle_index].in_use = true;
|
||||||
strncpy(dir_handles[handle_index].path, pathForCheck, 255);
|
|
||||||
|
dir_handles[handle_index].path[0] = '\0';
|
||||||
|
strncat(dir_handles[handle_index].path, pathForCheck, sizeof(dir_handles[handle_index].path) - 1);
|
||||||
|
|
||||||
DCFlushRange(&dir_handles[handle_index], sizeof(dirMagic_t));
|
DCFlushRange(&dir_handles[handle_index], sizeof(dirMagic_t));
|
||||||
OSUnlockMutex(dir_handles[handle_index].mutex);
|
OSUnlockMutex(dir_handles[handle_index].mutex);
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("Dir not found %s", pathForCheck);
|
DEBUG_FUNCTION_LINE("Dir not found %s", pathForCheck);
|
||||||
|
if (gReplacementInfo.contentReplacementInfo.fallbackOnError) {
|
||||||
|
return FS_STATUS_USE_REAL_OS;
|
||||||
|
}
|
||||||
if (errorMask & FS_ERROR_FLAG_NOT_FOUND) {
|
if (errorMask & FS_ERROR_FLAG_NOT_FOUND) {
|
||||||
result = FS_STATUS_NOT_FOUND;
|
result = FS_STATUS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
@ -183,7 +199,10 @@ FSStatus FSReadDirWrapper(FSDirectoryHandle handle,
|
|||||||
FSDirectoryEntry *entry,
|
FSDirectoryEntry *entry,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidDirHandle(handle)) {
|
|
||||||
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidDirHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +218,8 @@ FSStatus FSReadDirWrapper(FSDirectoryHandle handle,
|
|||||||
struct dirent *entry_ = readdir(dir);
|
struct dirent *entry_ = readdir(dir);
|
||||||
FSStatus result = FS_STATUS_END;
|
FSStatus result = FS_STATUS_END;
|
||||||
if (entry_) {
|
if (entry_) {
|
||||||
strncpy(entry->name, entry_->d_name, 254);
|
entry->name[0] = '\0';
|
||||||
|
strncat(entry->name, entry_->d_name, sizeof(entry->name)-1);
|
||||||
entry->info.mode = (FSMode) FS_MODE_READ_OWNER;
|
entry->info.mode = (FSMode) FS_MODE_READ_OWNER;
|
||||||
if (entry_->d_type == DT_DIR) {
|
if (entry_->d_type == DT_DIR) {
|
||||||
entry->info.flags = (FSStatFlags) ((uint32_t) FS_STAT_DIRECTORY);
|
entry->info.flags = (FSStatFlags) ((uint32_t) FS_STAT_DIRECTORY);
|
||||||
@ -231,7 +251,9 @@ FSStatus FSReadDirWrapper(FSDirectoryHandle handle,
|
|||||||
FSStatus FSCloseDirWrapper(FSDirectoryHandle handle,
|
FSStatus FSCloseDirWrapper(FSDirectoryHandle handle,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidDirHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidDirHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
uint32_t handle_index = handle & HANDLE_MASK;
|
uint32_t handle_index = handle & HANDLE_MASK;
|
||||||
@ -257,7 +279,9 @@ FSStatus FSCloseDirWrapper(FSDirectoryHandle handle,
|
|||||||
FSStatus FSRewindDirWrapper(FSDirectoryHandle handle,
|
FSStatus FSRewindDirWrapper(FSDirectoryHandle handle,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidDirHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidDirHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
uint32_t handle_index = handle & HANDLE_MASK;
|
uint32_t handle_index = handle & HANDLE_MASK;
|
||||||
@ -278,7 +302,9 @@ FSStatus FSMakeDirWrapper(char *path,
|
|||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(char *_path)> fallback_function,
|
std::function<FSStatus(char *_path)> fallback_function,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +333,8 @@ FSStatus FSOpenFileWrapper(char *path,
|
|||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(char *_path)> fallback_function,
|
std::function<FSStatus(char *_path)> fallback_function,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
if (path == nullptr) {
|
if (path == nullptr) {
|
||||||
@ -318,6 +345,7 @@ FSStatus FSOpenFileWrapper(char *path,
|
|||||||
char pathForCheck[256];
|
char pathForCheck[256];
|
||||||
|
|
||||||
getFullPath(pathForCheck, sizeof(pathForCheck), path);
|
getFullPath(pathForCheck, sizeof(pathForCheck), path);
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("%s -> %s", path, pathForCheck);
|
||||||
|
|
||||||
if (checkForSave(pathForCheck, sizeof(pathForCheck), pathForCheck)) {
|
if (checkForSave(pathForCheck, sizeof(pathForCheck), pathForCheck)) {
|
||||||
DEBUG_FUNCTION_LINE("Redirect save to %s", pathForCheck);
|
DEBUG_FUNCTION_LINE("Redirect save to %s", pathForCheck);
|
||||||
@ -329,8 +357,9 @@ FSStatus FSOpenFileWrapper(char *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(pathForCheck, "/vol/content", 12) == 0) {
|
if (strncmp(pathForCheck, "/vol/content", 12) == 0) {
|
||||||
memcpy(pathForCheck, "rom:", 4);
|
replaceContentPath(pathForCheck, sizeof(pathForCheck), 12, gReplacementInfo.contentReplacementInfo.replacementPath);
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Trying to open %s", pathForCheck);
|
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("%s -> %s", path, pathForCheck);
|
||||||
int handle_index = getNewFileHandleIndex();
|
int handle_index = getNewFileHandleIndex();
|
||||||
FSStatus result = FS_STATUS_OK;
|
FSStatus result = FS_STATUS_OK;
|
||||||
if (handle_index >= 0) {
|
if (handle_index >= 0) {
|
||||||
@ -368,17 +397,24 @@ FSStatus FSOpenFileWrapper(char *path,
|
|||||||
DCFlushRange(&file_handles[handle_index], sizeof(fileMagic_t));
|
DCFlushRange(&file_handles[handle_index], sizeof(fileMagic_t));
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("File not found %s", pathForCheck);
|
DEBUG_FUNCTION_LINE("File not found %s", pathForCheck);
|
||||||
if (errorMask & FS_ERROR_FLAG_NOT_FOUND) {
|
if (gReplacementInfo.contentReplacementInfo.fallbackOnError) {
|
||||||
|
result = FS_STATUS_USE_REAL_OS;
|
||||||
|
} else if (errorMask & FS_ERROR_FLAG_NOT_FOUND) {
|
||||||
result = FS_STATUS_NOT_FOUND;
|
result = FS_STATUS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OSUnlockMutex(file_handles[handle_index].mutex);
|
OSUnlockMutex(file_handles[handle_index].mutex);
|
||||||
} else {
|
} else {
|
||||||
if (errorMask & FS_ERROR_FLAG_MAX) {
|
if (gReplacementInfo.contentReplacementInfo.fallbackOnError) {
|
||||||
|
result = FS_STATUS_USE_REAL_OS;
|
||||||
|
} else if (errorMask & FS_ERROR_FLAG_MAX) {
|
||||||
result = FS_STATUS_MAX;
|
result = FS_STATUS_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result_handler(result);
|
if (result != FS_STATUS_USE_REAL_OS) {
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("return error %d", result);
|
||||||
|
return result_handler(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
@ -386,7 +422,9 @@ FSStatus FSOpenFileWrapper(char *path,
|
|||||||
FSStatus FSCloseFileWrapper(FSFileHandle handle,
|
FSStatus FSCloseFileWrapper(FSFileHandle handle,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidFileHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +455,8 @@ FSStatus FSCloseFileWrapper(FSFileHandle handle,
|
|||||||
FSStatus FSGetStatWrapper(char *path, FSStat *stats, FSErrorFlag errorMask,
|
FSStatus FSGetStatWrapper(char *path, FSStat *stats, FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(char *_path)> fallback_function,
|
std::function<FSStatus(char *_path)> fallback_function,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
if (path == nullptr) {
|
if (path == nullptr) {
|
||||||
@ -429,22 +468,30 @@ FSStatus FSGetStatWrapper(char *path, FSStat *stats, FSErrorFlag errorMask,
|
|||||||
|
|
||||||
getFullPath(pathForCheck, sizeof(pathForCheck), path);
|
getFullPath(pathForCheck, sizeof(pathForCheck), path);
|
||||||
|
|
||||||
if (checkForSave(pathForCheck, sizeof(pathForCheck), pathForCheck)) {
|
if (gReplacementInfo.contentReplacementInfo.replaceSave &&
|
||||||
|
checkForSave(pathForCheck, sizeof(pathForCheck), pathForCheck)) {
|
||||||
DEBUG_FUNCTION_LINE("Redirect save to %s", pathForCheck);
|
DEBUG_FUNCTION_LINE("Redirect save to %s", pathForCheck);
|
||||||
return fallback_function(pathForCheck);
|
return fallback_function(pathForCheck);
|
||||||
}
|
}
|
||||||
if (strncmp(pathForCheck, "/vol/content", 12) == 0) {
|
if (strncmp(pathForCheck, "/vol/content", 12) == 0) {
|
||||||
memcpy(pathForCheck, "rom:", 4);
|
replaceContentPath(pathForCheck, sizeof(pathForCheck), 12, gReplacementInfo.contentReplacementInfo.replacementPath);
|
||||||
|
DEBUG_FUNCTION_LINE("%s -> %s", path, pathForCheck);
|
||||||
|
|
||||||
FSStatus result = FS_STATUS_OK;
|
FSStatus result = FS_STATUS_OK;
|
||||||
if (stats == nullptr) {
|
if (stats == nullptr) {
|
||||||
|
if (gReplacementInfo.contentReplacementInfo.fallbackOnError) {
|
||||||
|
return FS_STATUS_USE_REAL_OS;
|
||||||
|
}
|
||||||
DEBUG_FUNCTION_LINE("Invalid args");
|
DEBUG_FUNCTION_LINE("Invalid args");
|
||||||
return FS_STATUS_FATAL_ERROR;
|
return FS_STATUS_FATAL_ERROR;
|
||||||
} else {
|
} else {
|
||||||
struct stat path_stat{};
|
struct stat path_stat{};
|
||||||
memset(&path_stat, 0, sizeof(path_stat));
|
memset(&path_stat, 0, sizeof(path_stat));
|
||||||
if (stat(pathForCheck, &path_stat) < 0) {
|
if (stat(pathForCheck, &path_stat) < 0) {
|
||||||
DEBUG_FUNCTION_LINE("Path not found %s", pathForCheck);
|
if (gReplacementInfo.contentReplacementInfo.fallbackOnError) {
|
||||||
if (errorMask & FS_ERROR_FLAG_NOT_FOUND) {
|
return FS_STATUS_USE_REAL_OS;
|
||||||
|
} else if (errorMask & FS_ERROR_FLAG_NOT_FOUND) {
|
||||||
|
DEBUG_FUNCTION_LINE("Path not found %s", pathForCheck);
|
||||||
result = FS_STATUS_NOT_FOUND;
|
result = FS_STATUS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -466,11 +513,26 @@ FSStatus FSGetStatWrapper(char *path, FSStat *stats, FSErrorFlag errorMask,
|
|||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void replaceContentPath(char *pathForCheck, int pathForCheckSize, int skipLen, char *replaceWith) {
|
||||||
|
int subStrLen = strlen(pathForCheck) - skipLen;
|
||||||
|
if (subStrLen <= 0) {
|
||||||
|
pathForCheck[0] = '\0';
|
||||||
|
strncat(pathForCheck, replaceWith, sizeof(pathForCheck) - 1);
|
||||||
|
} else {
|
||||||
|
char pathCopy[subStrLen+1];
|
||||||
|
pathCopy[0] = '\0';
|
||||||
|
strncat(pathCopy, &pathForCheck[skipLen], sizeof(pathCopy) - 1);
|
||||||
|
snprintf(pathForCheck, pathForCheckSize, "%s%s", replaceWith, pathCopy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FSStatus FSGetStatFileWrapper(FSFileHandle handle,
|
FSStatus FSGetStatFileWrapper(FSFileHandle handle,
|
||||||
FSStat *stats,
|
FSStat *stats,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidFileHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
uint32_t handle_index = handle & HANDLE_MASK;
|
uint32_t handle_index = handle & HANDLE_MASK;
|
||||||
@ -511,7 +573,9 @@ FSStatus FSReadFileWrapper(void *buffer,
|
|||||||
uint32_t unk1,
|
uint32_t unk1,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidFileHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
uint32_t handle_index = handle & HANDLE_MASK;
|
uint32_t handle_index = handle & HANDLE_MASK;
|
||||||
@ -556,7 +620,9 @@ FSStatus FSReadFileWithPosWrapper(void *buffer,
|
|||||||
int32_t unk1,
|
int32_t unk1,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidFileHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
FSStatus result;
|
FSStatus result;
|
||||||
@ -579,7 +645,9 @@ FSStatus FSSetPosFileWrapper(FSFileHandle handle,
|
|||||||
uint32_t pos,
|
uint32_t pos,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidFileHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +677,9 @@ FSStatus FSGetPosFileWrapper(FSFileHandle handle,
|
|||||||
uint32_t *pos,
|
uint32_t *pos,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidFileHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
uint32_t handle_index = handle & HANDLE_MASK;
|
uint32_t handle_index = handle & HANDLE_MASK;
|
||||||
@ -640,7 +710,9 @@ FSStatus FSGetPosFileWrapper(FSFileHandle handle,
|
|||||||
FSStatus FSIsEofWrapper(FSFileHandle handle,
|
FSStatus FSIsEofWrapper(FSFileHandle handle,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidFileHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
uint32_t handle_index = handle & HANDLE_MASK;
|
uint32_t handle_index = handle & HANDLE_MASK;
|
||||||
@ -674,7 +746,10 @@ FSStatus FSIsEofWrapper(FSFileHandle handle,
|
|||||||
FSStatus FSTruncateFileWrapper(FSFileHandle handle,
|
FSStatus FSTruncateFileWrapper(FSFileHandle handle,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidFileHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
uint32_t handle_index = handle & HANDLE_MASK;
|
uint32_t handle_index = handle & HANDLE_MASK;
|
||||||
@ -697,7 +772,10 @@ FSStatus FSWriteFileWrapper(uint8_t *buffer,
|
|||||||
uint32_t unk1,
|
uint32_t unk1,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) ||
|
||||||
|
!isValidFileHandle(handle)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
FSStatus result = FS_STATUS_OK;
|
FSStatus result = FS_STATUS_OK;
|
||||||
@ -711,7 +789,9 @@ FSStatus FSRemoveWrapper(char *path,
|
|||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(char *_path)> fallback_function,
|
std::function<FSStatus(char *_path)> fallback_function,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -740,7 +820,9 @@ FSStatus FSRenameWrapper(char *oldPath,
|
|||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
std::function<FSStatus(char *_oldPath, char *_newPath)> fallback_function,
|
std::function<FSStatus(char *_oldPath, char *_newPath)> fallback_function,
|
||||||
std::function<FSStatus(FSStatus)> result_handler) {
|
std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,10 +849,13 @@ FSStatus FSRenameWrapper(char *oldPath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
FSStatus FSFlushFileWrapper(FSFileHandle handle, FSErrorFlag errorMask, std::function<FSStatus(FSStatus)> result_handler) {
|
FSStatus FSFlushFileWrapper(FSFileHandle handle, FSErrorFlag errorMask, std::function<FSStatus(FSStatus)> result_handler) {
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted || !isValidFileHandle(handle)) {
|
if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) ||
|
||||||
|
(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) {
|
||||||
return FS_STATUS_USE_REAL_OS;
|
return FS_STATUS_USE_REAL_OS;
|
||||||
}
|
}
|
||||||
FSStatus result = FS_STATUS_OK;
|
FSStatus result = FS_STATUS_OK;
|
||||||
|
|
||||||
if (errorMask & FS_ERROR_FLAG_ACCESS_ERROR) {
|
if (errorMask & FS_ERROR_FLAG_ACCESS_ERROR) {
|
||||||
result = FS_STATUS_ACCESS_ERROR;
|
result = FS_STATUS_ACCESS_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ typedef struct dirMagic {
|
|||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
bool in_use;
|
bool in_use;
|
||||||
char path[255];
|
char path[256];
|
||||||
OSMutex *mutex;
|
OSMutex *mutex;
|
||||||
} dirMagic_t;
|
} dirMagic_t;
|
||||||
|
|
||||||
|
@ -21,11 +21,12 @@
|
|||||||
* Patch the meta xml for the home menu
|
* 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) {
|
DECL_FUNCTION(int32_t, HBM_NN_ACP_ACPGetTitleMetaXmlByDevice, uint32_t titleid_upper, uint32_t titleid_lower, ACPMetaXml *metaxml, uint32_t device) {
|
||||||
if (gReplacementInfo.isRPXReplaced) {
|
if (gReplacementInfo.rpxReplacementInfo.isRPXReplaced) {
|
||||||
memset(&metaxml->longname_ja, 0, 0x338C - 0x38C); // clear all names
|
memset(&metaxml->longname_ja, 0, 0x338C - 0x38C); // clear all names
|
||||||
strncpy(metaxml->longname_en, gReplacementInfo.metaInformation.longname, sizeof(gReplacementInfo.metaInformation.longname));
|
|
||||||
strncpy(metaxml->shortname_en, gReplacementInfo.metaInformation.shortname, sizeof(gReplacementInfo.metaInformation.shortname));
|
snprintf(metaxml->longname_en, sizeof(metaxml->longname_en), "%s", gReplacementInfo.rpxReplacementInfo.metaInformation.longname);
|
||||||
strncpy(metaxml->publisher_en, gReplacementInfo.metaInformation.author, sizeof(gReplacementInfo.metaInformation.author));
|
snprintf(metaxml->shortname_en, sizeof(metaxml->shortname_en), "%s", gReplacementInfo.rpxReplacementInfo.metaInformation.longname);
|
||||||
|
snprintf(metaxml->publisher_en, sizeof(metaxml->publisher_en), "%s", gReplacementInfo.rpxReplacementInfo.metaInformation.longname);
|
||||||
|
|
||||||
// Disbale the emanual
|
// Disbale the emanual
|
||||||
metaxml->e_manual = 0;
|
metaxml->e_manual = 0;
|
||||||
@ -39,9 +40,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) {
|
DECL_FUNCTION(int, RPX_FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, const char *mode, int *handle, int error) {
|
||||||
const char *iconTex = "iconTex.tga";
|
const char *iconTex = "iconTex.tga";
|
||||||
if (StringTools::EndsWith(path, iconTex)) {
|
if (StringTools::EndsWith(path, iconTex)) {
|
||||||
if (gReplacementInfo.isRPXReplaced) {
|
if (gReplacementInfo.rpxReplacementInfo.isRPXReplaced) {
|
||||||
if (StringTools::EndsWith(path, iconTex)) {
|
if (StringTools::EndsWith(path, iconTex)) {
|
||||||
auto *reader = new FileReader(reinterpret_cast<uint8_t *>(gReplacementInfo.iconCache), sizeof(gReplacementInfo.iconCache));
|
auto *reader = new FileReader(reinterpret_cast<uint8_t *>(gReplacementInfo.rpxReplacementInfo.iconCache), sizeof(gReplacementInfo.rpxReplacementInfo.iconCache));
|
||||||
*handle = (uint32_t) reader;
|
*handle = (uint32_t) reader;
|
||||||
return FS_STATUS_OK;
|
return FS_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -92,11 +93,14 @@ static int parseINIhandler(void *user, const char *section, const char *name,
|
|||||||
auto *fInfo = (MetaInformation *) user;
|
auto *fInfo = (MetaInformation *) user;
|
||||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
||||||
if (MATCH("menu", "longname")) {
|
if (MATCH("menu", "longname")) {
|
||||||
strncpy(fInfo->longname, value, 64 - 1);
|
fInfo->longname[0] = '\0';
|
||||||
|
strncat(fInfo->longname, value, sizeof(fInfo->longname) - 1);
|
||||||
} else if (MATCH("menu", "shortname")) {
|
} else if (MATCH("menu", "shortname")) {
|
||||||
strncpy(fInfo->shortname, value, 64 - 1);
|
fInfo->shortname[0] = '\0';
|
||||||
|
strncat(fInfo->shortname, value, sizeof(fInfo->shortname) - 1);
|
||||||
} else if (MATCH("menu", "author")) {
|
} else if (MATCH("menu", "author")) {
|
||||||
strncpy(fInfo->author, value, 64 - 1);
|
fInfo->author[0] = '\0';
|
||||||
|
strncat(fInfo->author, value, sizeof(fInfo->author) - 1);
|
||||||
} else {
|
} else {
|
||||||
return 0; /* unknown section/name, error */
|
return 0; /* unknown section/name, error */
|
||||||
}
|
}
|
||||||
@ -110,26 +114,23 @@ bool RL_LoadFromSDOnNextLaunch(const char *bundle_path) {
|
|||||||
|
|
||||||
request.command = 0xFC; // IPC_CUSTOM_LOAD_CUSTOM_RPX;
|
request.command = 0xFC; // IPC_CUSTOM_LOAD_CUSTOM_RPX;
|
||||||
request.target = 0; // LOAD_FILE_TARGET_SD_CARD
|
request.target = 0; // LOAD_FILE_TARGET_SD_CARD
|
||||||
request.filesize = 0; // unknown
|
request.filesize = 0; // unknown filesize
|
||||||
request.fileoffset = 0; //
|
request.fileoffset = 0; //
|
||||||
|
|
||||||
romfs_fileInfo info;
|
romfs_fileInfo info;
|
||||||
|
|
||||||
bool metaLoaded = false;
|
bool metaLoaded = false;
|
||||||
|
|
||||||
gReplacementInfo.replacementType = RPXLoader_RPX;
|
|
||||||
|
|
||||||
std::string completePath = std::string("/vol/external01/") + bundle_path;
|
std::string completePath = std::string("/vol/external01/") + bundle_path;
|
||||||
int res = getRPXInfoForPath(completePath, &info);
|
int res = getRPXInfoForPath(completePath, &info);
|
||||||
bool isBundle = false;
|
bool isBundle = false;
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
gReplacementInfo.replacementType = RPXLoader_BUNDLE;
|
|
||||||
isBundle = true;
|
isBundle = true;
|
||||||
request.filesize = ((uint32_t *) &info.length)[1];
|
request.filesize = ((uint32_t *) &info.length)[1];
|
||||||
request.fileoffset = ((uint32_t *) &info.offset)[1];
|
request.fileoffset = ((uint32_t *) &info.offset)[1];
|
||||||
|
|
||||||
if (romfsMount("rcc", completePath.c_str(), RomfsSource_FileDescriptor_CafeOS) == 0) {
|
if (romfsMount("rcc", completePath.c_str(), RomfsSource_FileDescriptor_CafeOS) == 0) {
|
||||||
if (ini_parse("rcc:/meta/meta.ini", parseINIhandler, &gReplacementInfo.metaInformation) < 0) {
|
if (ini_parse("rcc:/meta/meta.ini", parseINIhandler, &gReplacementInfo.rpxReplacementInfo.metaInformation) < 0) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to load and parse meta.ini");
|
DEBUG_FUNCTION_LINE("Failed to load and parse meta.ini");
|
||||||
} else {
|
} else {
|
||||||
metaLoaded = true;
|
metaLoaded = true;
|
||||||
@ -145,30 +146,40 @@ bool RL_LoadFromSDOnNextLaunch(const char *bundle_path) {
|
|||||||
}
|
}
|
||||||
if (reader) {
|
if (reader) {
|
||||||
uint32_t alreadyRead = 0;
|
uint32_t alreadyRead = 0;
|
||||||
uint32_t toRead = sizeof(gReplacementInfo.iconCache);
|
uint32_t toRead = sizeof(gReplacementInfo.rpxReplacementInfo.iconCache);
|
||||||
do {
|
do {
|
||||||
int read = reader->read(reinterpret_cast<uint8_t *>(&gReplacementInfo.iconCache[alreadyRead]), toRead);
|
int read = reader->read(reinterpret_cast<uint8_t *>(&gReplacementInfo.rpxReplacementInfo.iconCache[alreadyRead]), toRead);
|
||||||
if (read <= 0) {
|
if (read <= 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
alreadyRead += read;
|
alreadyRead += read;
|
||||||
toRead -= read;
|
toRead -= read;
|
||||||
} while (alreadyRead < sizeof(gReplacementInfo.iconCache));
|
} while (alreadyRead < sizeof(gReplacementInfo.rpxReplacementInfo.iconCache));
|
||||||
delete reader;
|
delete reader;
|
||||||
} else {
|
} else {
|
||||||
memset(gReplacementInfo.iconCache, 0, sizeof(gReplacementInfo.iconCache));
|
memset(gReplacementInfo.rpxReplacementInfo.iconCache, 0, sizeof(gReplacementInfo.rpxReplacementInfo.iconCache));
|
||||||
}
|
}
|
||||||
romfsUnmount("rcc");
|
romfsUnmount("rcc");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE &&
|
||||||
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) {
|
||||||
|
memset(gReplacementInfo.rpxReplacementInfo.iconCache, 0, sizeof(gReplacementInfo.rpxReplacementInfo.iconCache));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!metaLoaded) {
|
if (!metaLoaded) {
|
||||||
strncpy(gReplacementInfo.metaInformation.author, bundle_path, sizeof(gReplacementInfo.metaInformation.author));
|
gReplacementInfo.rpxReplacementInfo.metaInformation.author[0] = '\0';
|
||||||
strncpy(gReplacementInfo.metaInformation.shortname, bundle_path, sizeof(gReplacementInfo.metaInformation.shortname));
|
gReplacementInfo.rpxReplacementInfo.metaInformation.shortname[0] = '\0';
|
||||||
strncpy(gReplacementInfo.metaInformation.longname, bundle_path, sizeof(gReplacementInfo.metaInformation.longname));
|
gReplacementInfo.rpxReplacementInfo.metaInformation.longname[0] = '\0';
|
||||||
|
|
||||||
|
strncat(gReplacementInfo.rpxReplacementInfo.metaInformation.author, bundle_path, sizeof(gReplacementInfo.rpxReplacementInfo.metaInformation.author) - 1);
|
||||||
|
strncat(gReplacementInfo.rpxReplacementInfo.metaInformation.shortname, bundle_path, sizeof(gReplacementInfo.rpxReplacementInfo.metaInformation.shortname) - 1);
|
||||||
|
strncat(gReplacementInfo.rpxReplacementInfo.metaInformation.longname, bundle_path, sizeof(gReplacementInfo.rpxReplacementInfo.metaInformation.longname) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(request.path, bundle_path, 255);
|
request.path[0] = '\0';
|
||||||
|
strncat(request.path, bundle_path, sizeof(request.path) - 1);
|
||||||
|
|
||||||
DCFlushRange(&request, sizeof(LOAD_REQUEST));
|
DCFlushRange(&request, sizeof(LOAD_REQUEST));
|
||||||
|
|
||||||
@ -187,27 +198,33 @@ bool RL_LoadFromSDOnNextLaunch(const char *bundle_path) {
|
|||||||
DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo));
|
DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo));
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
gReplacementInfo.replacementType = RPXLoader_NONE;
|
gReplacementInfo.rpxReplacementInfo.isRPXReplaced = false;
|
||||||
DEBUG_FUNCTION_LINE("Failed to load %s on next restart", request.path);
|
DEBUG_FUNCTION_LINE("Failed to load %s on next restart", request.path);
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
gReplacementInfo.rpxReplacementInfo.isRPXReplaced = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Launch %s on next restart [size: %08X offset: %08X]", request.path, request.filesize, request.fileoffset);
|
DEBUG_FUNCTION_LINE("Launch %s on next restart [size: %08X offset: %08X]", request.path, request.filesize, request.fileoffset);
|
||||||
|
|
||||||
if (isBundle) {
|
if (isBundle) {
|
||||||
DEBUG_FUNCTION_LINE("Loaded file is a .wuhb bundle");
|
DEBUG_FUNCTION_LINE("Loaded file is a .wuhb bundle");
|
||||||
memset(gReplacementInfo.bundleMountInformation.path, 0, sizeof(gReplacementInfo.bundleMountInformation.path));
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath[0] = '\0';
|
||||||
strncpy(gReplacementInfo.bundleMountInformation.path, completePath.c_str(), completePath.length());
|
strncat(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath,
|
||||||
gReplacementInfo.replacementType = RPXLoader_BUNDLE;
|
completePath.c_str(),
|
||||||
gReplacementInfo.bundleMountInformation.redirectionRequested = true;
|
sizeof(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath) - 1);
|
||||||
|
gReplacementInfo.contentReplacementInfo.mode = CONTENTREDIRECT_FROM_WUHB_BUNDLE;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("Loaded file is no bundle");
|
DEBUG_FUNCTION_LINE("Loaded file is no bundle");
|
||||||
if (!gReplacementInfo.bundleMountInformation.isMounted) {
|
gReplacementInfo.rpxReplacementInfo.isRPXReplaced = true;
|
||||||
memset(gReplacementInfo.bundleMountInformation.path, 0, sizeof(gReplacementInfo.bundleMountInformation.path));
|
|
||||||
} else {
|
if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE &&
|
||||||
gReplacementInfo.replacementType = RPXLoader_BUNDLE_OTHER_RPX;
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) {
|
||||||
gReplacementInfo.bundleMountInformation.redirectionRequested = true;
|
|
||||||
// keep the old /vol/content mounted, this way you can reload just the rpx via wiiload
|
// keep the old /vol/content mounted, this way you can reload just the rpx via wiiload
|
||||||
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath[0] = '\0';
|
||||||
|
strncat(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath,
|
||||||
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath,
|
||||||
|
sizeof(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,27 +8,43 @@ typedef struct MetaInformation_t {
|
|||||||
} MetaInformation;
|
} MetaInformation;
|
||||||
|
|
||||||
typedef struct BundleMountInformation_t {
|
typedef struct BundleMountInformation_t {
|
||||||
bool redirectionRequested;
|
|
||||||
bool isMounted;
|
bool isMounted;
|
||||||
char path[255];
|
char toMountPath[255];
|
||||||
char workingDir[255];
|
char mountedPath[255];
|
||||||
} BundleMountInformation;
|
} BundleMountInformation;
|
||||||
|
|
||||||
typedef enum RPXLoader_Type {
|
typedef struct RPXReplacementInfo_t {
|
||||||
RPXLoader_NONE,
|
|
||||||
RPXLoader_RPX,
|
|
||||||
RPXLoader_BUNDLE,
|
|
||||||
RPXLoader_BUNDLE_OTHER_RPX,
|
|
||||||
} RPXLoader_Type;
|
|
||||||
|
|
||||||
typedef struct RPXLoader_ReplacementInformation_t {
|
|
||||||
bool isRPXReplaced;
|
bool isRPXReplaced;
|
||||||
MetaInformation metaInformation;
|
MetaInformation metaInformation;
|
||||||
RPXLoader_Type replacementType;
|
|
||||||
BundleMountInformation bundleMountInformation;
|
|
||||||
char iconCache[65580];
|
char iconCache[65580];
|
||||||
uint32_t currentHash;
|
} RPXReplacementInfo;
|
||||||
|
|
||||||
|
typedef enum ContentRedirect_Mode {
|
||||||
|
CONTENTREDIRECT_NONE,
|
||||||
|
CONTENTREDIRECT_FROM_WUHB_BUNDLE,
|
||||||
|
CONTENTREDIRECT_FROM_PATH,
|
||||||
|
} ContentRedirect_Mode;
|
||||||
|
|
||||||
|
typedef struct ContentReplacementInfo_t {
|
||||||
|
ContentRedirect_Mode mode;
|
||||||
|
|
||||||
|
BundleMountInformation bundleMountInformation;
|
||||||
|
|
||||||
|
char workingDir[255];
|
||||||
|
|
||||||
|
char replacementPath[255];
|
||||||
|
|
||||||
|
bool replaceSave;
|
||||||
|
|
||||||
char savePath[255];
|
char savePath[255];
|
||||||
|
|
||||||
|
bool fallbackOnError;
|
||||||
|
} ContentReplacementInfo;
|
||||||
|
|
||||||
|
typedef struct RPXLoader_ReplacementInformation_t {
|
||||||
|
RPXReplacementInfo rpxReplacementInfo;
|
||||||
|
ContentReplacementInfo contentReplacementInfo;
|
||||||
} RPXLoader_ReplacementInformation;
|
} RPXLoader_ReplacementInformation;
|
||||||
|
|
||||||
|
|
||||||
extern RPXLoader_ReplacementInformation gReplacementInfo;
|
extern RPXLoader_ReplacementInformation gReplacementInfo;
|
85
src/main.cpp
85
src/main.cpp
@ -32,11 +32,16 @@ WUMS_INITIALIZE() {
|
|||||||
|
|
||||||
|
|
||||||
WUMS_APPLICATION_ENDS() {
|
WUMS_APPLICATION_ENDS() {
|
||||||
if (gReplacementInfo.bundleMountInformation.isMounted) {
|
if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) {
|
||||||
DEBUG_FUNCTION_LINE("Unmount /vol/content");
|
gReplacementInfo.contentReplacementInfo.mode = CONTENTREDIRECT_NONE;
|
||||||
romfsUnmount("rom");
|
}
|
||||||
gReplacementInfo.bundleMountInformation.isMounted = false;
|
if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE) {
|
||||||
DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo));
|
if (gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) {
|
||||||
|
DEBUG_FUNCTION_LINE("Unmount /vol/content");
|
||||||
|
romfsUnmount("rom");
|
||||||
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false;
|
||||||
|
DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,46 +51,56 @@ WUMS_APPLICATION_STARTS() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WHBLogUdpInit();
|
WHBLogUdpInit();
|
||||||
|
if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) != OSGetTitleID()) {
|
if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) != OSGetTitleID()) {
|
||||||
DEBUG_FUNCTION_LINE("Set gTryToReplaceOnNextLaunch, gReplacedRPX and gIsMounted to FALSE");
|
DEBUG_FUNCTION_LINE("Set gTryToReplaceOnNextLaunch, gReplacedRPX and gIsMounted to FALSE");
|
||||||
gReplacementInfo.replacementType = RPXLoader_NONE;
|
gReplacementInfo.contentReplacementInfo.mode = CONTENTREDIRECT_NONE;
|
||||||
gReplacementInfo.isRPXReplaced = false;
|
|
||||||
gReplacementInfo.bundleMountInformation.isMounted = false;
|
|
||||||
gReplacementInfo.bundleMountInformation.redirectionRequested = false;
|
|
||||||
DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo));
|
DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo));
|
||||||
} else {
|
} else {
|
||||||
if (gReplacementInfo.replacementType != RPXLoader_NONE) {
|
if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE) {
|
||||||
gReplacementInfo.isRPXReplaced = true;
|
uint32_t currentHash = StringTools::hash(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath);
|
||||||
}
|
|
||||||
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::Initialize();
|
||||||
nn::act::SlotNo slot = nn::act::GetSlotNo();
|
nn::act::PersistentId slot = nn::act::GetPersistentId();
|
||||||
nn::act::Finalize();
|
nn::act::Finalize();
|
||||||
|
|
||||||
std::string basePath = StringTools::strfmt("/vol/external01/wiiu/apps/save/%08X", gReplacementInfo.currentHash);
|
std::string basePath = StringTools::strfmt("/vol/external01/wiiu/apps/save/%08X", currentHash);
|
||||||
std::string common = StringTools::strfmt("fs:/vol/external01/wiiu/apps/save/%08X/common", gReplacementInfo.currentHash);
|
std::string common = StringTools::strfmt("fs:/vol/external01/wiiu/apps/save/%08X/common", currentHash);
|
||||||
std::string user = StringTools::strfmt("fs:/vol/external01/wiiu/apps/save/%08X/%08X", gReplacementInfo.currentHash, 0x80000000 | slot);
|
std::string user = StringTools::strfmt("fs:/vol/external01/wiiu/apps/save/%08X/%08X", currentHash, 0x80000000 | slot);
|
||||||
|
|
||||||
strncpy(gReplacementInfo.savePath, basePath.c_str(), sizeof(gReplacementInfo.savePath));
|
gReplacementInfo.contentReplacementInfo.savePath[0] = '\0';
|
||||||
memset(gReplacementInfo.bundleMountInformation.workingDir, 0, sizeof(gReplacementInfo.bundleMountInformation.workingDir));
|
strncat(gReplacementInfo.contentReplacementInfo.savePath,
|
||||||
|
basePath.c_str(),
|
||||||
|
sizeof(gReplacementInfo.contentReplacementInfo.savePath) - 1);
|
||||||
|
|
||||||
CreateSubfolder(common.c_str());
|
memset(gReplacementInfo.contentReplacementInfo.workingDir, 0, sizeof(gReplacementInfo.contentReplacementInfo.workingDir));
|
||||||
CreateSubfolder(user.c_str());
|
|
||||||
DEBUG_FUNCTION_LINE("Created %s and %s", common.c_str(), user.c_str());
|
CreateSubfolder(common.c_str());
|
||||||
if (romfsMount("rom", gReplacementInfo.bundleMountInformation.path, RomfsSource_FileDescriptor_CafeOS) == 0) {
|
CreateSubfolder(user.c_str());
|
||||||
DEBUG_FUNCTION_LINE("Mounted %s to /vol/content", gReplacementInfo.bundleMountInformation.path);
|
DEBUG_FUNCTION_LINE("Created %s and %s", common.c_str(), user.c_str());
|
||||||
gReplacementInfo.bundleMountInformation.isMounted = true;
|
if (romfsMount("rom", gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath, RomfsSource_FileDescriptor_CafeOS) == 0) {
|
||||||
} else {
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath[0] = '\0';
|
||||||
DEBUG_FUNCTION_LINE("Failed to mount %s", gReplacementInfo.bundleMountInformation.path);
|
strncat(gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath,
|
||||||
gReplacementInfo.bundleMountInformation.isMounted = false;
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath,
|
||||||
}
|
sizeof(gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath) - 1);
|
||||||
} else if (gReplacementInfo.replacementType == RPXLoader_RPX) {
|
|
||||||
//
|
|
||||||
|
gReplacementInfo.contentReplacementInfo.replacementPath[0] = '\0';
|
||||||
|
strncat(gReplacementInfo.contentReplacementInfo.replacementPath,
|
||||||
|
"rom:/content",
|
||||||
|
sizeof(gReplacementInfo.contentReplacementInfo.replacementPath) - 1);
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("Mounted %s to /vol/content", gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath);
|
||||||
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = true;
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE("Failed to mount %s", gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath);
|
||||||
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo));
|
DCFlushRange(&gReplacementInfo, sizeof(gReplacementInfo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user