From ebe901ebdcc292b2c845bec942dcfc3fdac743e4 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sat, 12 Mar 2022 21:21:21 +0100 Subject: [PATCH] Rewrite to use libcontentredirection and libwuhbutils. --- Dockerfile | 8 +- Makefile | 20 +- src/FSDirReplacements.cpp | 194 ------ src/FSDirReplacements.h | 15 - src/FSFileReplacements.cpp | 399 ----------- src/FSFileReplacements.h | 15 - src/FSWrapper.cpp | 1012 ---------------------------- src/FSWrapper.h | 160 ----- src/FileUtils.cpp | 178 +---- src/FileUtils.h | 16 +- src/RPXLoading.cpp | 328 ++++----- src/RPXLoading.h | 3 + src/contentredirection.def | 4 + src/globals.cpp | 6 +- src/globals.h | 38 +- src/main.cpp | 187 ++--- src/utils/FileReader.cpp | 4 +- src/utils/FileReader.h | 4 +- src/utils/FileReaderCompressed.cpp | 89 --- src/utils/FileReaderCompressed.h | 25 - src/utils/StringTools.cpp | 317 +-------- src/utils/StringTools.h | 87 +-- src/utils/logger.h | 21 +- src/wuhbutils.def | 4 + 24 files changed, 367 insertions(+), 2767 deletions(-) delete mode 100644 src/FSDirReplacements.cpp delete mode 100644 src/FSDirReplacements.h delete mode 100644 src/FSFileReplacements.cpp delete mode 100644 src/FSFileReplacements.h delete mode 100644 src/FSWrapper.cpp delete mode 100644 src/FSWrapper.h create mode 100644 src/contentredirection.def delete mode 100644 src/utils/FileReaderCompressed.cpp delete mode 100644 src/utils/FileReaderCompressed.h create mode 100644 src/wuhbutils.def diff --git a/Dockerfile b/Dockerfile index bbfd448..503183f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,10 @@ -FROM wiiuenv/devkitppc:20220303 +FROM wiiuenv/devkitppc:20220417 -COPY --from=wiiuenv/librpxloader:20220212 /artifacts $DEVKITPRO +COPY --from=wiiuenv/librpxloader:20220417 /artifacts $DEVKITPRO COPY --from=wiiuenv/libfunctionpatcher:20220211 /artifacts $DEVKITPRO COPY --from=wiiuenv/wiiumodulesystem:20220204 /artifacts $DEVKITPRO -COPY --from=wiiuenv/libromfs_wiiu:20220305 /artifacts $DEVKITPRO +COPY --from=wiiuenv/libwuhbutils:20220415 /artifacts $DEVKITPRO +COPY --from=wiiuenv/libcontentredirection:20220414 /artifacts $DEVKITPRO +COPY --from=wiiuenv/libromfs_wiiu:20220414 /artifacts $DEVKITPRO WORKDIR project \ No newline at end of file diff --git a/Makefile b/Makefile index 09cfce1..9953f09 100644 --- a/Makefile +++ b/Makefile @@ -34,17 +34,17 @@ CFLAGS := -Wall -Wextra -Os -ffunction-sections\ CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -CXXFLAGS := $(CFLAGS) -std=c++17 +CXXFLAGS := $(CFLAGS) -std=c++20 ASFLAGS := -g $(ARCH) -LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/libfunctionpatcher.ld $(WUMSSPECS) +LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/libfunctionpatcher.ld -Tcontentredirection.ld -Twuhbutils.ld $(WUMSSPECS) ifeq ($(DEBUG),1) CXXFLAGS += -DDEBUG -g CFLAGS += -DDEBUG -g endif -LIBS := -lwums -lwut -lfunctionpatcher -lromfs -lz +LIBS := -lwums -lwut -lfunctionpatcher -lcontentredirection -lwuhbutils -lromfs #------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level @@ -71,6 +71,7 @@ export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +DEFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.def))) BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) #------------------------------------------------------------------------------- @@ -88,7 +89,7 @@ endif #------------------------------------------------------------------------------- export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES_SRC := $(DEFFILES:.def=.o) $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) export OFILES := $(OFILES_BIN) $(OFILES_SRC) export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) @@ -128,11 +129,18 @@ $(OUTPUT).elf : $(OFILES) $(OFILES_SRC) : $(HFILES_BIN) + #------------------------------------------------------------------------------- # you need a rule like this for each extension you use as binary data #------------------------------------------------------------------------------- -%.bin.o %_bin.h : %.bin -#------------------------------------------------------------------------------- +%.o: %.def + $(SILENTMSG) $(notdir $<) + $(SILENTCMD)rplimportgen $< $*.s $*.ld $(ERROR_FILTER) + $(SILENTCMD)$(CC) -x assembler-with-cpp $(ASFLAGS) -c $*.s -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%_bin.h %.bin.o : %.bin +#--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) diff --git a/src/FSDirReplacements.cpp b/src/FSDirReplacements.cpp deleted file mode 100644 index 3ba0624..0000000 --- a/src/FSDirReplacements.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include "FSDirReplacements.h" -#include "FSWrapper.h" -#include "FileUtils.h" -#include "globals.h" -#include "utils/logger.h" -#include -#include - -#define SYNC_RESULT_HANDLER [](FSStatus res) -> FSStatus { \ - return res; \ -} - -#define ASYNC_RESULT_HANDLER [client, block, asyncData](FSStatus res) -> FSStatus { \ - DEBUG_FUNCTION_LINE_VERBOSE("Result was %d", res); \ - return send_result_async(client, block, asyncData, res); \ -} - -DECL_FUNCTION(FSStatus, FSOpenDir, FSClient *client, FSCmdBlock *block, char *path, FSDirectoryHandle *handle, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSStatus result = FSOpenDirWrapper( - path, handle, errorMask, - [client, block, handle, errorMask](char *_path) -> FSStatus { - return real_FSOpenDir(client, block, _path, handle, errorMask); - }, - SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - DEBUG_FUNCTION_LINE_VERBOSE("Result was %d", result); - return result; - } - - return real_FSOpenDir(client, block, path, handle, errorMask); -} - -DECL_FUNCTION(FSStatus, FSOpenDirAsync, FSClient *client, FSCmdBlock *block, char *path, FSDirectoryHandle *handle, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSErrorFlag realErrorMask = errorMask; - - // Even real_FSOpenDir is still calling our FSOpenDirAsync hook. To bypass our code we use "FORCE_REAL_FUNC_WITH_FULL_ERRORS" as an errorMask. - if ((errorMask & ERROR_FLAG_MASK) != FORCE_REAL_FUNC_MAGIC) { - FSStatus result = FSOpenDirWrapper( - path, handle, errorMask, - [client, block, handle, errorMask, asyncData](char *_path) -> FSStatus { - return real_FSOpenDirAsync(client, block, _path, handle, errorMask, asyncData); - }, - ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - } else { - realErrorMask = FS_ERROR_FLAG_ALL; - } - - return real_FSOpenDirAsync(client, block, path, handle, realErrorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSReadDir, FSClient *client, FSCmdBlock *block, FSDirectoryHandle handle, FSDirectoryEntry *entry, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(); - FSStatus result = FSReadDirWrapper(handle, entry, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSReadDir(client, block, handle, entry, errorMask); -} - -DECL_FUNCTION(FSStatus, FSReadDirAsync, FSClient *client, FSCmdBlock *block, FSDirectoryHandle handle, FSDirectoryEntry *entry, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(); - FSErrorFlag realErrorMask = errorMask; - // Even real_FSReadDir is still calling our FSReadDirAsync hook. To bypass our code we use "FORCE_REAL_FUNC_WITH_FULL_ERRORS" as an errorMask. - if ((errorMask & ERROR_FLAG_MASK) != FORCE_REAL_FUNC_MAGIC) { - FSStatus result = FSReadDirWrapper(handle, entry, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - } else { - realErrorMask = FS_ERROR_FLAG_ALL; - } - - return real_FSReadDirAsync(client, block, handle, entry, realErrorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSCloseDir, FSClient *client, FSCmdBlock *block, FSDirectoryHandle handle, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(); - FSStatus result = FSCloseDirWrapper(handle, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSCloseDir(client, block, handle, errorMask); -} - -DECL_FUNCTION(FSStatus, FSCloseDirAsync, FSClient *client, FSCmdBlock *block, FSDirectoryHandle handle, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(); - FSErrorFlag realErrorMask = errorMask; - // Even real_FSCloseDir is still calling our FSCloseDirAsync hook. To bypass our code we use "FORCE_REAL_FUNC_WITH_FULL_ERRORS" as an errorMask. - if ((errorMask & ERROR_FLAG_MASK) != FORCE_REAL_FUNC_MAGIC) { - FSStatus result = FSCloseDirWrapper(handle, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - } else { - realErrorMask = FS_ERROR_FLAG_ALL; - } - - return real_FSCloseDirAsync(client, block, handle, realErrorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSRewindDir, FSClient *client, FSCmdBlock *block, FSDirectoryHandle handle, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(); - FSStatus result = FSRewindDirWrapper(handle, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSRewindDir(client, block, handle, errorMask); -} - -DECL_FUNCTION(FSStatus, FSRewindDirAsync, FSClient *client, FSCmdBlock *block, FSDirectoryHandle handle, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(); - FSErrorFlag realErrorMask = errorMask; - // Even real_FSRewindDir is still calling our FSRewindDirAsync hook. To bypass our code we use "FORCE_REAL_FUNC_WITH_FULL_ERRORS" as an errorMask. - if ((errorMask & ERROR_FLAG_MASK) != FORCE_REAL_FUNC_MAGIC) { - FSStatus result = FSRewindDirWrapper(handle, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - } else { - realErrorMask = FS_ERROR_FLAG_ALL; - } - - return real_FSRewindDirAsync(client, block, handle, realErrorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSMakeDir, FSClient *client, FSCmdBlock *block, char *path, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSStatus result = FSMakeDirWrapper( - path, errorMask, - [client, block, errorMask](char *_path) -> FSStatus { - return real_FSMakeDir(client, block, _path, errorMask); - }, - SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSMakeDir(client, block, path, errorMask); -} - -DECL_FUNCTION(FSStatus, FSMakeDirAsync, FSClient *client, FSCmdBlock *block, char *path, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSStatus result = FSMakeDirWrapper( - path, errorMask, - [client, block, errorMask, asyncData](char *_path) -> FSStatus { - return real_FSMakeDirAsync(client, block, _path, errorMask, asyncData); - }, - ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - 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); - auto len = strlen(gReplacementInfo.contentReplacementInfo.workingDir); - if (len > 0 && gReplacementInfo.contentReplacementInfo.workingDir[len - 1] != '/') { - gReplacementInfo.contentReplacementInfo.workingDir[len - 1] = '/'; - gReplacementInfo.contentReplacementInfo.workingDir[len] = 0; - } - OSMemoryBarrier(); - return real_FSChangeDirAsync(client, block, path, errorMask, asyncData); -} - -function_replacement_data_t fs_dir_function_replacements[] = { - REPLACE_FUNCTION(FSOpenDir, LIBRARY_COREINIT, FSOpenDir), - REPLACE_FUNCTION(FSOpenDirAsync, LIBRARY_COREINIT, FSOpenDirAsync), - - REPLACE_FUNCTION(FSReadDir, LIBRARY_COREINIT, FSReadDir), - REPLACE_FUNCTION(FSReadDirAsync, LIBRARY_COREINIT, FSReadDirAsync), - - REPLACE_FUNCTION(FSCloseDir, LIBRARY_COREINIT, FSCloseDir), - REPLACE_FUNCTION(FSCloseDirAsync, LIBRARY_COREINIT, FSCloseDirAsync), - - REPLACE_FUNCTION(FSRewindDir, LIBRARY_COREINIT, FSRewindDir), - REPLACE_FUNCTION(FSRewindDirAsync, LIBRARY_COREINIT, FSRewindDirAsync), - - REPLACE_FUNCTION(FSMakeDir, LIBRARY_COREINIT, FSMakeDir), - 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); \ No newline at end of file diff --git a/src/FSDirReplacements.h b/src/FSDirReplacements.h deleted file mode 100644 index 542f219..0000000 --- a/src/FSDirReplacements.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern function_replacement_data_t fs_dir_function_replacements[]; -extern uint32_t fs_dir_function_replacements_size; - -#ifdef __cplusplus -} -#endif diff --git a/src/FSFileReplacements.cpp b/src/FSFileReplacements.cpp deleted file mode 100644 index b7a0f43..0000000 --- a/src/FSFileReplacements.cpp +++ /dev/null @@ -1,399 +0,0 @@ -#include "FSFileReplacements.h" -#include "globals.h" - -#include -#include - -#include "FSWrapper.h" -#include "FileUtils.h" -#include "utils/logger.h" - -#define SYNC_RESULT_HANDLER [](FSStatus res) -> FSStatus { \ - return res; \ -} - -#define ASYNC_RESULT_HANDLER [client, block, asyncData](FSStatus res) -> FSStatus { \ - return send_result_async(client, block, asyncData, res); \ -} - -DECL_FUNCTION(FSStatus, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, const char *mode, FSFileHandle *handle, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSStatus result = FSOpenFileWrapper( - path, mode, handle, errorMask, - [client, block, mode, handle, errorMask](char *_path) -> FSStatus { - return real_FSOpenFile(client, block, _path, mode, handle, errorMask); - }, - SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - FSStatus res = real_FSOpenFile(client, block, path, mode, handle, errorMask); - return res; -} - -DECL_FUNCTION(FSStatus, FSOpenFileAsync, FSClient *client, FSCmdBlock *block, char *path, const char *mode, FSFileHandle *handle, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSStatus result = FSOpenFileWrapper( - path, mode, handle, errorMask, - [client, block, mode, handle, errorMask, asyncData](char *_path) -> FSStatus { - return real_FSOpenFileAsync(client, block, _path, mode, handle, errorMask, asyncData); - }, - ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSOpenFileAsync(client, block, path, mode, handle, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSCloseFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSCloseFileWrapper(handle, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - FSStatus res = real_FSCloseFile(client, block, handle, errorMask); - return res; -} - -DECL_FUNCTION(FSStatus, FSCloseFileAsync, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSCloseFileWrapper(handle, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSCloseFileAsync(client, block, handle, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSGetStat, FSClient *client, FSCmdBlock *block, char *path, FSStat *stats, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSStatus result = FSGetStatWrapper( - path, stats, errorMask, - [client, block, stats, errorMask](char *_path) -> FSStatus { - return real_FSGetStat(client, block, _path, stats, errorMask); - }, - SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - return real_FSGetStat(client, block, path, stats, errorMask); -} - -DECL_FUNCTION(FSStatus, FSGetStatAsync, FSClient *client, FSCmdBlock *block, char *path, FSStat *stats, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSStatus result = FSGetStatWrapper( - path, stats, errorMask, - [client, block, stats, errorMask, asyncData](char *_path) -> FSStatus { - return real_FSGetStatAsync(client, block, _path, stats, errorMask, asyncData); - }, - ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - return real_FSGetStatAsync(client, block, path, stats, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSGetStatFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSStat *stats, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSGetStatFileWrapper(handle, stats, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSGetStatFile(client, block, handle, stats, errorMask); -} - -DECL_FUNCTION(FSStatus, FSGetStatFileAsync, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSStat *stats, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSGetStatFileWrapper(handle, stats, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSGetStatFileAsync(client, block, handle, stats, errorMask, asyncData); -} - -DECL_FUNCTION(int32_t, FSReadFile, FSClient *client, FSCmdBlock *block, void *buffer, uint32_t size, uint32_t count, FSFileHandle handle, uint32_t unk1, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSReadFileWrapper(buffer, size, count, handle, unk1, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSReadFile(client, block, buffer, size, count, handle, unk1, errorMask); -} - -DECL_FUNCTION(int32_t, FSReadFileAsync, FSClient *client, FSCmdBlock *block, void *buffer, uint32_t size, uint32_t count, FSFileHandle handle, uint32_t unk1, FSErrorFlag errorMask, - FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSReadFileWrapper(buffer, size, count, handle, unk1, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return send_result_async(client, block, asyncData, result); - } - - return real_FSReadFileAsync(client, block, buffer, size, count, handle, unk1, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSReadFileWithPos, FSClient *client, FSCmdBlock *block, void *buffer, uint32_t size, uint32_t count, uint32_t pos, FSFileHandle handle, uint32_t unk1, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSReadFileWithPosWrapper(buffer, size, count, pos, handle, unk1, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - DEBUG_FUNCTION_LINE_VERBOSE("%d", size * count); - - FSStatus res = real_FSReadFileWithPos(client, block, buffer, size, count, pos, handle, unk1, errorMask); - return res; -} - -DECL_FUNCTION(int32_t, FSReadFileWithPosAsync, FSClient *client, FSCmdBlock *block, void *buffer, uint32_t size, uint32_t count, uint32_t pos, FSFileHandle handle, int32_t unk1, FSErrorFlag errorMask, - FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSReadFileWithPosWrapper(buffer, size, count, pos, handle, unk1, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSReadFileWithPosAsync(client, block, buffer, size, count, pos, handle, unk1, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSSetPosFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, uint32_t pos, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSSetPosFileWrapper(handle, pos, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - return real_FSSetPosFile(client, block, handle, pos, errorMask); -} - -DECL_FUNCTION(FSStatus, FSSetPosFileAsync, FSClient *client, FSCmdBlock *block, FSFileHandle handle, uint32_t pos, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSSetPosFileWrapper(handle, pos, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSSetPosFileAsync(client, block, handle, pos, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSGetPosFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, uint32_t *pos, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSGetPosFileWrapper(handle, pos, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - return real_FSGetPosFile(client, block, handle, pos, errorMask); -} - -DECL_FUNCTION(FSStatus, FSGetPosFileAsync, FSClient *client, FSCmdBlock *block, FSFileHandle handle, uint32_t *pos, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSGetPosFileWrapper(handle, pos, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSGetPosFileAsync(client, block, handle, pos, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSIsEof, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSIsEofWrapper(handle, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - return real_FSIsEof(client, block, handle, errorMask); -} - -DECL_FUNCTION(FSStatus, FSIsEofAsync, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSIsEofWrapper(handle, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - return real_FSIsEofAsync(client, block, handle, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSWriteFile, FSClient *client, FSCmdBlock *block, uint8_t *buffer, uint32_t size, uint32_t count, FSFileHandle handle, uint32_t unk1, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSWriteFileWrapper(buffer, size, count, handle, unk1, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSWriteFile(client, block, buffer, size, count, handle, unk1, errorMask); -} - -DECL_FUNCTION(FSStatus, FSWriteFileAsync, FSClient *client, FSCmdBlock *block, uint8_t *buffer, uint32_t size, uint32_t count, FSFileHandle handle, uint32_t unk1, FSErrorFlag errorMask, - FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSWriteFileWrapper(buffer, size, count, handle, unk1, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSWriteFileAsync(client, block, buffer, size, count, handle, unk1, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSTruncateFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSTruncateFileWrapper(handle, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSTruncateFile(client, block, handle, errorMask); -} - -DECL_FUNCTION(FSStatus, FSTruncateFileAsync, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSTruncateFileWrapper(handle, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSTruncateFileAsync(client, block, handle, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSRemove, FSClient *client, FSCmdBlock *block, char *path, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSStatus result = FSRemoveWrapper( - path, errorMask, - [client, block, errorMask](char *_path) -> FSStatus { - return real_FSRemove(client, block, _path, errorMask); - }, - SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSRemove(client, block, path, errorMask); -} - -DECL_FUNCTION(FSStatus, FSRemoveAsync, FSClient *client, FSCmdBlock *block, char *path, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE("%s", path); - FSStatus result = FSRemoveWrapper( - path, errorMask, - [client, block, errorMask, asyncData](char *_path) -> FSStatus { - return real_FSRemoveAsync(client, block, _path, errorMask, asyncData); - }, - ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSRemoveAsync(client, block, path, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSRename, FSClient *client, FSCmdBlock *block, char *oldPath, char *newPath, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE("%s %s", oldPath, newPath); - FSStatus result = FSRenameWrapper( - oldPath, newPath, errorMask, - [client, block, errorMask](char *_oldOath, char *_newPath) -> FSStatus { - return real_FSRename(client, block, _oldOath, _newPath, errorMask); - }, - SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSRename(client, block, oldPath, newPath, errorMask); -} - -DECL_FUNCTION(FSStatus, FSRenameAsync, FSClient *client, FSCmdBlock *block, char *oldPath, char *newPath, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE("%s %s", oldPath, newPath); - FSStatus result = FSRenameWrapper( - oldPath, newPath, errorMask, - [client, block, errorMask, asyncData](char *_oldOath, char *_newPath) -> FSStatus { - return real_FSRenameAsync(client, block, _oldOath, _newPath, errorMask, asyncData); - }, - ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSRenameAsync(client, block, oldPath, newPath, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSFlushFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSErrorFlag errorMask) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSFlushFileWrapper(handle, errorMask, SYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSFlushFile(client, block, handle, errorMask); -} - -DECL_FUNCTION(FSStatus, FSFlushFileAsync, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE(""); - FSStatus result = FSFlushFileWrapper(handle, errorMask, ASYNC_RESULT_HANDLER); - if (result != FS_STATUS_USE_REAL_OS) { - return result; - } - - return real_FSFlushFileAsync(client, block, handle, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSChangeModeAsync, FSClient *client, FSCmdBlock *block, char *path, FSMode mode, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE("FSChangeModeAsync %s", path); - return real_FSChangeModeAsync(client, block, path, mode, errorMask, asyncData); -} - -DECL_FUNCTION(FSStatus, FSGetFreeSpaceSizeAsync, FSClient *client, FSCmdBlock *block, char *path, uint64_t *outSize, FSErrorFlag errorMask, FSAsyncData *asyncData) { - DEBUG_FUNCTION_LINE_VERBOSE("FSGetFreeSpaceSizeAsync %s", path); - return real_FSGetFreeSpaceSizeAsync(client, block, path, outSize, errorMask, asyncData); -} - - -function_replacement_data_t fs_file_function_replacements[] = { - REPLACE_FUNCTION(FSOpenFile, LIBRARY_COREINIT, FSOpenFile), - REPLACE_FUNCTION(FSOpenFileAsync, LIBRARY_COREINIT, FSOpenFileAsync), - - REPLACE_FUNCTION(FSCloseFile, LIBRARY_COREINIT, FSCloseFile), - REPLACE_FUNCTION(FSCloseFileAsync, LIBRARY_COREINIT, FSCloseFileAsync), - - REPLACE_FUNCTION(FSGetStat, LIBRARY_COREINIT, FSGetStat), - REPLACE_FUNCTION(FSGetStatAsync, LIBRARY_COREINIT, FSGetStatAsync), - - REPLACE_FUNCTION(FSGetStatFile, LIBRARY_COREINIT, FSGetStatFile), - REPLACE_FUNCTION(FSGetStatFileAsync, LIBRARY_COREINIT, FSGetStatFileAsync), - - REPLACE_FUNCTION(FSReadFile, LIBRARY_COREINIT, FSReadFile), - REPLACE_FUNCTION(FSReadFileAsync, LIBRARY_COREINIT, FSReadFileAsync), - - REPLACE_FUNCTION(FSReadFileWithPos, LIBRARY_COREINIT, FSReadFileWithPos), - REPLACE_FUNCTION(FSReadFileWithPosAsync, LIBRARY_COREINIT, FSReadFileWithPosAsync), - - REPLACE_FUNCTION(FSSetPosFile, LIBRARY_COREINIT, FSSetPosFile), - REPLACE_FUNCTION(FSSetPosFileAsync, LIBRARY_COREINIT, FSSetPosFileAsync), - - REPLACE_FUNCTION(FSGetPosFile, LIBRARY_COREINIT, FSGetPosFile), - REPLACE_FUNCTION(FSGetPosFileAsync, LIBRARY_COREINIT, FSGetPosFileAsync), - - REPLACE_FUNCTION(FSIsEof, LIBRARY_COREINIT, FSIsEof), - REPLACE_FUNCTION(FSIsEofAsync, LIBRARY_COREINIT, FSIsEofAsync), - - REPLACE_FUNCTION(FSWriteFile, LIBRARY_COREINIT, FSWriteFile), - REPLACE_FUNCTION(FSWriteFileAsync, LIBRARY_COREINIT, FSWriteFileAsync), - - REPLACE_FUNCTION(FSTruncateFile, LIBRARY_COREINIT, FSTruncateFile), - REPLACE_FUNCTION(FSTruncateFileAsync, LIBRARY_COREINIT, FSTruncateFileAsync), - - REPLACE_FUNCTION(FSRemove, LIBRARY_COREINIT, FSRemove), - REPLACE_FUNCTION(FSRemoveAsync, LIBRARY_COREINIT, FSRemoveAsync), - - REPLACE_FUNCTION(FSRename, LIBRARY_COREINIT, FSRename), - REPLACE_FUNCTION(FSRenameAsync, LIBRARY_COREINIT, FSRenameAsync), - - REPLACE_FUNCTION(FSFlushFile, LIBRARY_COREINIT, FSFlushFile), - REPLACE_FUNCTION(FSFlushFileAsync, LIBRARY_COREINIT, FSFlushFileAsync), - - //REPLACE_FUNCTION(FSChangeModeAsync, LIBRARY_COREINIT, FSChangeModeAsync), - - //REPLACE_FUNCTION(FSGetFreeSpaceSizeAsync, LIBRARY_COREINIT, FSGetFreeSpaceSizeAsync), -}; - -uint32_t fs_file_function_replacements_size = sizeof(fs_file_function_replacements) / sizeof(function_replacement_data_t); \ No newline at end of file diff --git a/src/FSFileReplacements.h b/src/FSFileReplacements.h deleted file mode 100644 index ce06bb2..0000000 --- a/src/FSFileReplacements.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern function_replacement_data_t fs_file_function_replacements[]; -extern uint32_t fs_file_function_replacements_size; - -#ifdef __cplusplus -} -#endif diff --git a/src/FSWrapper.cpp b/src/FSWrapper.cpp deleted file mode 100644 index 41203a5..0000000 --- a/src/FSWrapper.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -#include "FSWrapper.h" -#include "FileUtils.h" -#include "globals.h" -#include "utils/logger.h" -#include -#include -#include -#include -#include -#include -#include -#include - -dirMagic_t dir_handles[DIR_HANDLES_LENGTH]; -fileMagic_t file_handles[FILE_HANDLES_LENGTH]; - -std::mutex dir_handle_mutex; -std::mutex file_handle_mutex; - -static inline void replaceContentPath(char *pathForCheck, size_t pathForCheckSize, int replaceLen, char *replaceWith); - -inline void getFullPath(char *pathForCheck, int pathSize, char *path) { - if (path[0] != '/' && path[0] != '\\') { - snprintf(pathForCheck, pathSize, "%s%s", gReplacementInfo.contentReplacementInfo.workingDir, path); - DEBUG_FUNCTION_LINE_VERBOSE("Real path is %s", pathForCheck); - } else { - pathForCheck[0] = '\0'; - strncat(pathForCheck, path, pathSize - 1); - } - - for (size_t i = 0; i < strlen(pathForCheck); i++) { - if (pathForCheck[i] == '\\') { - pathForCheck[i] = '/'; - } - } -} - -inline bool checkForSave(char *pathForCheck, int pathSize, char *path) { - if (!gReplacementInfo.contentReplacementInfo.replaceSave) { - return false; - } - if (strncmp(path, "/vol/save", 9) == 0) { - int copyLen = strlen(path); - char copy[copyLen + 1]; - memcpy(copy, path, copyLen); - copy[copyLen] = 0; - memset(pathForCheck, 0, pathSize); - snprintf(pathForCheck, pathSize, "%s%s", gReplacementInfo.contentReplacementInfo.savePath, ©[9]); - return true; - } - return false; -} - -int getNewFileHandleIndex() { - file_handle_mutex.lock(); - int32_t handle_id = -1; - for (int i = 0; i < FILE_HANDLES_LENGTH; i++) { - if (!file_handles[i].in_use) { - handle_id = i; - if (!file_handles[i].mutex) { - file_handles[i].mutex = (OSMutex *) malloc(sizeof(OSMutex)); - if (!file_handles[i].mutex) { - OSFatal("Failed to alloc memory for mutex"); - } - OSInitMutex(file_handles[i].mutex); - OSMemoryBarrier(); - } - break; - } - } - file_handle_mutex.unlock(); - return handle_id; -} - -bool isValidDirHandle(uint32_t handle) { - return (handle & HANDLE_INDICATOR_MASK) == DIR_HANDLE_MAGIC; -} - -bool isValidFileHandle(uint32_t handle) { - return (handle & HANDLE_INDICATOR_MASK) == FILE_HANDLE_MAGIC; -} - -int32_t getNewDirHandleIndex() { - dir_handle_mutex.lock(); - int32_t handle_id = -1; - for (int i = 0; i < DIR_HANDLES_LENGTH; i++) { - if (!dir_handles[i].in_use) { - handle_id = i; - if (!dir_handles[i].mutex) { - dir_handles[i].mutex = (OSMutex *) malloc(sizeof(OSMutex)); - OSInitMutex(dir_handles[i].mutex); - if (!dir_handles[i].mutex) { - OSFatal("Failed to alloc memory for mutex"); - } - OSMemoryBarrier(); - } - break; - } - } - dir_handle_mutex.unlock(); - return handle_id; -} - -void freeFileHandle(uint32_t handle) { - if (handle >= FILE_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return; - } - file_handle_mutex.lock(); - file_handles[handle].in_use = false; - if (file_handles[handle].mutex) { - free(file_handles[handle].mutex); - file_handles[handle].mutex = nullptr; - } - OSMemoryBarrier(); - file_handle_mutex.unlock(); -} - -void freeDirHandle(uint32_t handle) { - if (handle >= DIR_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return; - } - dir_handle_mutex.lock(); - dir_handles[handle].in_use = false; - if (dir_handles[handle].mutex) { - free(dir_handles[handle].mutex); - dir_handles[handle].mutex = nullptr; - } - dir_handles[handle] = {}; - OSMemoryBarrier(); - dir_handle_mutex.unlock(); -} - -extern "C" FSStatus (*real_FSOpenDir)(FSClient *, FSCmdBlock *, char *, FSDirectoryHandle *, FSErrorFlag); - -FSStatus FSOpenDirWrapper(char *path, - FSDirectoryHandle *handle, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler) { - if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) || - (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) { - return FS_STATUS_USE_REAL_OS; - } - - char pathForCheck[256]; - - getFullPath(pathForCheck, sizeof(pathForCheck), path); - - if (checkForSave(pathForCheck, sizeof(pathForCheck), pathForCheck)) { - DEBUG_FUNCTION_LINE("Redirect save to %s", pathForCheck); - return fallback_function(pathForCheck); - } - if (handle == nullptr) { - DEBUG_FUNCTION_LINE("Invalid args"); - return FS_STATUS_FATAL_ERROR; - } - - if (strncmp(pathForCheck, "/vol/content", 12) == 0) { - replaceContentPath(pathForCheck, sizeof(pathForCheck), 12, gReplacementInfo.contentReplacementInfo.replacementPath); - - DEBUG_FUNCTION_LINE_VERBOSE("%s -> %s", path, pathForCheck); - FSStatus result = FS_STATUS_OK; - - int handle_index = getNewDirHandleIndex(); - - if (handle_index >= 0) { - DIR *dir; - if ((dir = opendir(pathForCheck))) { - OSLockMutex(dir_handles[handle_index].mutex); - dir_handles[handle_index].handle = DIR_HANDLE_MAGIC | handle_index; - *handle = dir_handles[handle_index].handle; - dir_handles[handle_index].dir = dir; - dir_handles[handle_index].in_use = true; - - dir_handles[handle_index].path[0] = '\0'; - strncat(dir_handles[handle_index].path, pathForCheck, sizeof(dir_handles[handle_index].path) - 1); - - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) { - auto dir_info = &dir_handles[handle_index]; - - dir_info->readResult = nullptr; - dir_info->readResultCapacity = 0; - dir_info->readResultNumberOfEntries = 0; - - dir_info->realDirHandle = 0; - - if (gFSClient && gFSCmd) { - FSDirectoryHandle realHandle = 0; - if (real_FSOpenDir(gFSClient, gFSCmd, path, &realHandle, (FSErrorFlag) FORCE_REAL_FUNC_WITH_FULL_ERRORS) == FS_STATUS_OK) { - dir_info->realDirHandle = realHandle; - } else { - DEBUG_FUNCTION_LINE_VERBOSE("Failed to open real dir %s", path); - } - } else { - DEBUG_FUNCTION_LINE("Global FSClient or FSCmdBlock were null"); - } - OSMemoryBarrier(); - } - - OSUnlockMutex(dir_handles[handle_index].mutex); - } else { - if (gReplacementInfo.contentReplacementInfo.fallbackOnError) { - return FS_STATUS_USE_REAL_OS; - } - if (errorMask & FS_ERROR_FLAG_NOT_FOUND) { - result = FS_STATUS_NOT_FOUND; - } - } - } else { - if (errorMask & FS_ERROR_FLAG_MAX) { - result = FS_STATUS_MAX; - } - } - return result_handler(result); - } - return FS_STATUS_USE_REAL_OS; -} - -extern "C" FSStatus (*real_FSReadDir)(FSClient *client, FSCmdBlock *block, FSDirectoryHandle handle, FSDirectoryEntry *entry, FSErrorFlag errorMask); - -FSStatus FSReadDirWrapper(FSDirectoryHandle handle, - FSDirectoryEntry *entry, - [[maybe_unused]] FSErrorFlag errorMask, - const std::function &result_handler) { - - 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; - } - - uint32_t handle_index = handle & HANDLE_MASK; - if (handle_index >= DIR_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return result_handler(FS_STATUS_FATAL_ERROR); - } - - OSLockMutex(dir_handles[handle_index].mutex); - DIR *dir = dir_handles[handle_index].dir; - - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) { - auto dir_info = &dir_handles[handle_index]; - - // Init list if needed - if (dir_info->readResultCapacity == 0) { - dir_info->readResult = (FSDirectoryEntry *) malloc(sizeof(FSDirectoryEntry)); - if (dir_info->readResult != nullptr) { - dir_info->readResultCapacity = 1; - } - } - OSMemoryBarrier(); - } - - struct dirent *entry_ = readdir(dir); - FSStatus result = FS_STATUS_END; - if (entry_) { - entry->name[0] = '\0'; - strncat(entry->name, entry_->d_name, sizeof(entry->name) - 1); - entry->info.mode = (FSMode) FS_MODE_READ_OWNER; - if (entry_->d_type == DT_DIR) { - entry->info.flags = (FSStatFlags) ((uint32_t) FS_STAT_DIRECTORY); - entry->info.size = 0; - } else { - entry->info.flags = (FSStatFlags) 0; - if (strcmp(entry_->d_name, ".") == 0 || strcmp(entry_->d_name, "..") == 0) { - entry->info.size = 0; - } else { - struct stat sb {}; - int strLen = strlen(dir_handles[handle_index].path) + 1 + strlen(entry_->d_name) + 1; - char path[strLen]; - snprintf(path, sizeof(path), "%s/%s", dir_handles[handle_index].path, entry_->d_name); - if (stat(path, &sb) >= 0) { - entry->info.size = sb.st_size; - entry->info.flags = (FSStatFlags) 0; - entry->info.owner = sb.st_uid; - entry->info.group = sb.st_gid; - } - } - } - - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) { - auto dir_info = &dir_handles[handle_index]; - if (dir_info->readResultNumberOfEntries >= dir_info->readResultCapacity) { - auto newCapacity = dir_info->readResultCapacity * 2; - dir_info->readResult = (FSDirectoryEntry *) realloc(dir_info->readResult, newCapacity * sizeof(FSDirectoryEntry)); - dir_info->readResultCapacity = newCapacity; - if (dir_info->readResult == nullptr) { - OSFatal("Failed to alloc memory for dir entry list"); - } - } - - memcpy(&dir_info->readResult[dir_info->readResultNumberOfEntries], entry, sizeof(FSDirectoryEntry)); - dir_info->readResultNumberOfEntries++; - - OSMemoryBarrier(); - } - - result = FS_STATUS_OK; - } else if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) { - auto dir_info = &dir_handles[handle_index]; - // Read the real directory. - if (dir_info->realDirHandle != 0) { - if (gFSClient && gFSCmd) { - FSDirectoryEntry realDirEntry; - FSStatus readDirResult = FS_STATUS_OK; - result = FS_STATUS_END; - while (readDirResult == FS_STATUS_OK) { - readDirResult = real_FSReadDir(gFSClient, gFSCmd, dir_info->realDirHandle, &realDirEntry, (FSErrorFlag) FORCE_REAL_FUNC_WITH_FULL_ERRORS); - if (readDirResult == FS_STATUS_OK) { - bool found = false; - for (int i = 0; i < dir_info->readResultNumberOfEntries; i++) { - auto curResult = &dir_info->readResult[i]; - // Check if this is a new result - if (strncmp(curResult->name, realDirEntry.name, sizeof(realDirEntry.name) - 1) == 0) { - found = true; - break; - } - } - // If it's new we can use it :) - if (!found) { - memcpy(entry, &realDirEntry, sizeof(FSDirectoryEntry)); - result = FS_STATUS_OK; - break; - } - } else if (readDirResult == FS_STATUS_END) { - result = FS_STATUS_END; - break; - } else { - DEBUG_FUNCTION_LINE("real_FSReadDir returned an unexpected error: %08X", readDirResult); - result = FS_STATUS_END; - break; - } - } - } else { - DEBUG_FUNCTION_LINE("Global FSClient or FSCmdBlock were null"); - } - } - } - - OSUnlockMutex(dir_handles[handle_index].mutex); - return result_handler(result); -} - -extern "C" FSStatus (*real_FSCloseDir)(FSClient *client, FSCmdBlock *block, FSDirectoryHandle handle, FSErrorFlag errorMask); - -FSStatus FSCloseDirWrapper(FSDirectoryHandle handle, - [[maybe_unused]] FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - uint32_t handle_index = handle & HANDLE_MASK; - if (handle_index >= DIR_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return FS_STATUS_FATAL_ERROR; - } - - OSLockMutex(dir_handles[handle_index].mutex); - - DIR *dir = dir_handles[handle_index].dir; - - FSStatus result = FS_STATUS_OK; - if (closedir(dir) != 0) { - result = FS_STATUS_MEDIA_ERROR; - } - - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) { - auto dir_info = &dir_handles[handle_index]; - - if (dir_info->realDirHandle != 0) { - if (gFSClient && gFSCmd) { - auto realResult = real_FSCloseDir(gFSClient, gFSCmd, dir_info->realDirHandle, (FSErrorFlag) FORCE_REAL_FUNC_WITH_FULL_ERRORS); - if (realResult == FS_STATUS_OK) { - dir_info->realDirHandle = 0; - } else { - DEBUG_FUNCTION_LINE("Failed to closed dir %d", realResult); - } - } else { - DEBUG_FUNCTION_LINE("Global FSClient or FSCmdBlock were null"); - } - } - - if (dir_info->readResult != nullptr) { - free(dir_info->readResult); - dir_info->readResult = nullptr; - dir_info->readResultCapacity = 0; - dir_info->readResultNumberOfEntries = 0; - } - OSMemoryBarrier(); - } - - OSUnlockMutex(dir_handles[handle_index].mutex); - freeDirHandle(handle_index); - return result_handler(result); -} - -extern "C" FSStatus (*real_FSRewindDir)(FSClient *client, FSCmdBlock *block, FSDirectoryHandle handle, FSErrorFlag errorMask); - -FSStatus FSRewindDirWrapper(FSDirectoryHandle handle, - [[maybe_unused]] FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - uint32_t handle_index = handle & HANDLE_MASK; - if (handle_index >= DIR_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return FS_STATUS_FATAL_ERROR; - } - uint32_t real_handle = handle & HANDLE_MASK; - OSLockMutex(dir_handles[handle_index].mutex); - - DIR *dir = dir_handles[real_handle].dir; - rewinddir(dir); - - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) { - auto dir_info = &dir_handles[handle_index]; - - if (dir_info->readResult != nullptr) { - dir_info->readResultNumberOfEntries = 0; - memset(dir_info->readResult, 0, sizeof(FSDirectoryEntry) * dir_info->readResultCapacity); - } - - if (dir_info->realDirHandle != 0) { - if (gFSClient && gFSCmd) { - if (real_FSRewindDir(gFSClient, gFSCmd, dir_info->realDirHandle, (FSErrorFlag) FORCE_REAL_FUNC_WITH_FULL_ERRORS) == FS_STATUS_OK) { - dir_info->realDirHandle = 0; - } else { - DEBUG_FUNCTION_LINE("Failed to rewind dir"); - } - } else { - DEBUG_FUNCTION_LINE("Global FSClient or FSCmdBlock were null"); - } - } - OSMemoryBarrier(); - } - - OSUnlockMutex(dir_handles[handle_index].mutex); - return result_handler(FS_STATUS_OK); -} - -FSStatus FSMakeDirWrapper(char *path, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler) { - 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; - } - - char pathForCheck[256]; - - getFullPath(pathForCheck, sizeof(pathForCheck), path); - - if (checkForSave(pathForCheck, sizeof(pathForCheck), pathForCheck)) { - DEBUG_FUNCTION_LINE("Redirect save to %s", pathForCheck); - return fallback_function(pathForCheck); - } - - if (strncmp(pathForCheck, "/vol/content", 12) == 0) { - FSStatus result = FS_STATUS_OK; - if (errorMask & FS_ERROR_FLAG_ACCESS_ERROR) { - result = FS_STATUS_ACCESS_ERROR; - } - return result_handler(result); - } - return FS_STATUS_USE_REAL_OS; -} - -FSStatus FSOpenFileWrapper(char *path, - const char *mode, - FSFileHandle *handle, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler) { - if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) || - (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) { - return FS_STATUS_USE_REAL_OS; - } - if (path == nullptr) { - OSFatal("Invalid args"); - return FS_STATUS_FATAL_ERROR; - } - - char pathForCheck[256]; - - getFullPath(pathForCheck, sizeof(pathForCheck), path); - DEBUG_FUNCTION_LINE_VERBOSE("%s -> %s", path, pathForCheck); - - if (checkForSave(pathForCheck, sizeof(pathForCheck), pathForCheck)) { - DEBUG_FUNCTION_LINE("Redirect save to %s", pathForCheck); - return fallback_function(pathForCheck); - } - if (mode == nullptr || handle == nullptr) { - DEBUG_FUNCTION_LINE("Invalid args"); - return FS_STATUS_FATAL_ERROR; - } - - if (strncmp(pathForCheck, "/vol/content", 12) == 0) { - replaceContentPath(pathForCheck, sizeof(pathForCheck), 12, gReplacementInfo.contentReplacementInfo.replacementPath); - - DEBUG_FUNCTION_LINE_VERBOSE("%s -> %s", path, pathForCheck); - int handle_index = getNewFileHandleIndex(); - FSStatus result = FS_STATUS_OK; - if (handle_index >= 0) { - OSLockMutex(file_handles[handle_index].mutex); - int _mode = 0; - // Map flags to open modes - if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0) { - _mode = 0x000; - } else if (strcmp(mode, "r+") == 0) { - _mode = 0x002; - } else if (strcmp(mode, "w") == 0) { - _mode = 0x601; - } else if (strcmp(mode, "w+") == 0) { - _mode = 0x602; - } else if (strcmp(mode, "a") == 0) { - _mode = 0x209; - } else if (strcmp(mode, "a+") == 0) { - _mode = 0x20A; - } else { - //DEBUG_FUNCTION_LINE("%s", mode); - if (errorMask & FS_ERROR_FLAG_ACCESS_ERROR) { - result = FS_STATUS_ACCESS_ERROR; - } - } - - int32_t fd = open(pathForCheck, _mode); - if (fd >= 0) { - DEBUG_FUNCTION_LINE_VERBOSE("Opened %s as %d", pathForCheck, fd); - - file_handles[handle_index].handle = FILE_HANDLE_MAGIC + handle_index; - //DEBUG_FUNCTION_LINE("handle %08X", file_handles[handle_index].handle); - *handle = file_handles[handle_index].handle; - file_handles[handle_index].fd = fd; - file_handles[handle_index].in_use = true; - OSMemoryBarrier(); - } else { - DEBUG_FUNCTION_LINE("File not found %s", pathForCheck); - if (gReplacementInfo.contentReplacementInfo.fallbackOnError) { - result = FS_STATUS_USE_REAL_OS; - } else if (errorMask & FS_ERROR_FLAG_NOT_FOUND) { - result = FS_STATUS_NOT_FOUND; - } - } - OSUnlockMutex(file_handles[handle_index].mutex); - } else { - if (gReplacementInfo.contentReplacementInfo.fallbackOnError) { - result = FS_STATUS_USE_REAL_OS; - } else if (errorMask & FS_ERROR_FLAG_MAX) { - result = FS_STATUS_MAX; - } - } - 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; -} - -FSStatus FSCloseFileWrapper(FSFileHandle handle, - [[maybe_unused]] FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - - uint32_t handle_index = handle & HANDLE_MASK; - - if (handle_index >= FILE_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return FS_STATUS_FATAL_ERROR; - } - - OSLockMutex(file_handles[handle_index].mutex); - - int real_fd = file_handles[handle_index].fd; - file_handles[handle_index].in_use = false; - - DEBUG_FUNCTION_LINE_VERBOSE("closing %d", real_fd); - - FSStatus result = FS_STATUS_OK; - if (close(real_fd) != 0) { - result = FS_STATUS_MEDIA_ERROR; - } - OSUnlockMutex(file_handles[handle_index].mutex); - - freeFileHandle(handle_index); - return result_handler(result); -} - -FSStatus FSGetStatWrapper(char *path, FSStat *stats, FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler) { - if ((gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_NONE) || - (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && !gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) { - return FS_STATUS_USE_REAL_OS; - } - if (path == nullptr) { - OSFatal("Invalid args"); - return FS_STATUS_FATAL_ERROR; - } - - char pathForCheck[256]; - - getFullPath(pathForCheck, sizeof(pathForCheck), path); - - if (checkForSave(pathForCheck, sizeof(pathForCheck), pathForCheck)) { - DEBUG_FUNCTION_LINE("Redirect save to %s", pathForCheck); - return fallback_function(pathForCheck); - } - if (strncmp(pathForCheck, "/vol/content", 12) == 0) { - replaceContentPath(pathForCheck, sizeof(pathForCheck), 12, gReplacementInfo.contentReplacementInfo.replacementPath); - DEBUG_FUNCTION_LINE("%s -> %s", path, pathForCheck); - - FSStatus result = FS_STATUS_OK; - if (stats == nullptr) { - if (gReplacementInfo.contentReplacementInfo.fallbackOnError) { - return FS_STATUS_USE_REAL_OS; - } - DEBUG_FUNCTION_LINE("Invalid args"); - return FS_STATUS_FATAL_ERROR; - } else { - struct stat path_stat {}; - memset(&path_stat, 0, sizeof(path_stat)); - if (stat(pathForCheck, &path_stat) < 0) { - if (gReplacementInfo.contentReplacementInfo.fallbackOnError) { - 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; - } - } else { - memset(&(stats->flags), 0, sizeof(stats->flags)); - if (S_ISDIR(path_stat.st_mode)) { - stats->flags = (FSStatFlags) ((uint32_t) FS_STAT_DIRECTORY); - } else { - stats->size = path_stat.st_size; - stats->mode = (FSMode) FS_MODE_READ_OWNER; - stats->flags = (FSStatFlags) 0; - stats->owner = path_stat.st_uid; - stats->group = path_stat.st_gid; - } - DEBUG_FUNCTION_LINE_VERBOSE("stats file for %s, size %016lLX", path, stats->size); - } - } - return result_handler(result); - } - return FS_STATUS_USE_REAL_OS; -} - -static inline void replaceContentPath(char *pathForCheck, size_t pathForCheckSize, int skipLen, char *replaceWith) { - size_t subStrLen = strlen(pathForCheck) - skipLen; - if (subStrLen <= 0) { - pathForCheck[0] = '\0'; - if (strlen(replaceWith) + 1 <= pathForCheckSize) { - memcpy(pathForCheck, replaceWith, strlen(replaceWith) + 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, - FSStat *stats, - [[maybe_unused]] FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - uint32_t handle_index = handle & HANDLE_MASK; - - if (handle_index >= FILE_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return FS_STATUS_FATAL_ERROR; - } - - OSLockMutex(file_handles[handle_index].mutex); - - int real_fd = file_handles[handle_index].fd; - //DEBUG_FUNCTION_LINE("FSGetStatFileAsync real_fd %d", real_fd); - - struct stat path_stat {}; - - FSStatus result = FS_STATUS_OK; - if (fstat(real_fd, &path_stat) < 0) { - result = FS_STATUS_MEDIA_ERROR; - } else { - memset(&(stats->flags), 0, sizeof(stats->flags)); - - stats->size = path_stat.st_size; - stats->mode = (FSMode) FS_MODE_READ_OWNER; - stats->flags = (FSStatFlags) 0; - stats->owner = path_stat.st_uid; - stats->group = path_stat.st_gid; - } - - OSUnlockMutex(file_handles[handle_index].mutex); - return result_handler(result); -} - -FSStatus FSReadFileWrapper(void *buffer, - uint32_t size, - uint32_t count, - FSFileHandle handle, - [[maybe_unused]] uint32_t unk1, - [[maybe_unused]] FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - uint32_t handle_index = handle & HANDLE_MASK; - - if (handle_index >= FILE_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return FS_STATUS_FATAL_ERROR; - } - - if (size * count == 0) { - return result_handler(FS_STATUS_OK); - } - if (buffer == nullptr && (size * count != 0)) { - DEBUG_FUNCTION_LINE("Fatal read FSErrorFlag errorMask, buffer is null but size*count is not"); - return FS_STATUS_FATAL_ERROR; - } - - FSStatus result; - - OSLockMutex(file_handles[handle_index].mutex); - - int real_fd = file_handles[handle_index].fd; - - int32_t read = readIntoBuffer(real_fd, buffer, size, count); - - if (read < 0) { - DEBUG_FUNCTION_LINE("Failed to read from handle"); - result = FS_STATUS_MEDIA_ERROR; - } else { - result = (FSStatus) (read / size); - } - - OSUnlockMutex(file_handles[handle_index].mutex); - return result_handler(result); -} - -FSStatus FSReadFileWithPosWrapper(void *buffer, - uint32_t size, - uint32_t count, - uint32_t pos, - FSFileHandle handle, - int32_t unk1, - FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - - FSStatus result; - if ((result = FSSetPosFileWrapper(handle, pos, errorMask, - [](FSStatus res) -> FSStatus { return res; })) != FS_STATUS_OK) { - return result; - } - - result = FSReadFileWrapper(buffer, size, count, handle, unk1, errorMask, - [](FSStatus res) -> FSStatus { return res; }); - - if (result != FS_STATUS_USE_REAL_OS && result != FS_STATUS_FATAL_ERROR) { - return result_handler(result); - } - return result; -} - -FSStatus FSSetPosFileWrapper(FSFileHandle handle, - uint32_t pos, - [[maybe_unused]] FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - - uint32_t handle_index = handle & HANDLE_MASK; - - if (handle_index >= FILE_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return FS_STATUS_FATAL_ERROR; - } - - FSStatus result = FS_STATUS_OK; - OSLockMutex(file_handles[handle_index].mutex); - - int real_fd = file_handles[handle_index].fd; - - if (lseek(real_fd, (off_t) pos, SEEK_SET) != pos) { - DEBUG_FUNCTION_LINE("Seek failed"); - result = FS_STATUS_MEDIA_ERROR; - } - DEBUG_FUNCTION_LINE_VERBOSE("pos set to %d for %d", pos, real_fd); - - OSUnlockMutex(file_handles[handle_index].mutex); - return result_handler(result); -} - -FSStatus FSGetPosFileWrapper(FSFileHandle handle, - uint32_t *pos, - [[maybe_unused]] FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - uint32_t handle_index = handle & HANDLE_MASK; - - if (handle_index >= FILE_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return FS_STATUS_FATAL_ERROR; - } - - FSStatus result = FS_STATUS_OK; - OSLockMutex(file_handles[handle_index].mutex); - - int real_fd = file_handles[handle_index].fd; - - off_t currentPos = lseek(real_fd, (off_t) 0, SEEK_CUR); - if (currentPos == -1) { - DEBUG_FUNCTION_LINE("Failed to get current pos for %d", real_fd); - result = FS_STATUS_MEDIA_ERROR; - } else { - *pos = currentPos; - DEBUG_FUNCTION_LINE_VERBOSE("result was %d for %d", *pos, real_fd); - } - - OSUnlockMutex(file_handles[handle_index].mutex); - return result_handler(result); -} - -FSStatus FSIsEofWrapper(FSFileHandle handle, - [[maybe_unused]] FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - uint32_t handle_index = handle & HANDLE_MASK; - - if (handle_index >= FILE_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return FS_STATUS_FATAL_ERROR; - } - - FSStatus result = FS_STATUS_OK; - OSLockMutex(file_handles[handle_index].mutex); - - int real_fd = file_handles[handle_index].fd; - - off_t currentPos = lseek(real_fd, (off_t) 0, SEEK_CUR); - off_t endPos = lseek(real_fd, (off_t) 0, SEEK_END); - - if (currentPos == endPos) { - DEBUG_FUNCTION_LINE_VERBOSE("FSIsEof END for %d\n", real_fd); - result = FS_STATUS_END; - } else { - lseek(real_fd, currentPos, SEEK_CUR); - DEBUG_FUNCTION_LINE_VERBOSE("FSIsEof OK for %d\n", real_fd); - result = FS_STATUS_OK; - } - - OSUnlockMutex(file_handles[handle_index].mutex); - return result_handler(result); -} - -FSStatus FSTruncateFileWrapper(FSFileHandle handle, - FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - uint32_t handle_index = handle & HANDLE_MASK; - - if (handle_index >= FILE_HANDLES_LENGTH) { - DEBUG_FUNCTION_LINE("Invalid handle"); - return FS_STATUS_FATAL_ERROR; - } - FSStatus result = FS_STATUS_OK; - if (errorMask & FS_ERROR_FLAG_ACCESS_ERROR) { - result = FS_STATUS_ACCESS_ERROR; - } - return result_handler(result); -} - -FSStatus FSWriteFileWrapper([[maybe_unused]] uint8_t *buffer, - [[maybe_unused]] uint32_t size, - [[maybe_unused]] uint32_t count, - FSFileHandle handle, - [[maybe_unused]] uint32_t unk1, - FSErrorFlag errorMask, - const std::function &result_handler) { - 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; - } - FSStatus result = FS_STATUS_OK; - if (errorMask & FS_ERROR_FLAG_ACCESS_ERROR) { - result = FS_STATUS_ACCESS_ERROR; - } - return result_handler(result); -} - -FSStatus FSRemoveWrapper(char *path, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler) { - 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; - } - - if (path == nullptr) { - OSFatal("Invalid args"); - return FS_STATUS_USE_REAL_OS; - } - - char pathForCheck[256]; - - getFullPath(pathForCheck, sizeof(pathForCheck), path); - - if (checkForSave(pathForCheck, sizeof(pathForCheck), pathForCheck)) { - DEBUG_FUNCTION_LINE("Redirect save to %s", pathForCheck); - return fallback_function(pathForCheck); - } - FSStatus result = FS_STATUS_OK; - if (errorMask & FS_ERROR_FLAG_ACCESS_ERROR) { - result = FS_STATUS_ACCESS_ERROR; - } - return result_handler(result); -} - -FSStatus FSRenameWrapper(char *oldPath, - char *newPath, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler) { - 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; - } - - char pathForCheck1[256]; - char pathForCheck2[256]; - - getFullPath(pathForCheck1, sizeof(pathForCheck1), oldPath); - getFullPath(pathForCheck2, sizeof(pathForCheck2), newPath); - - if (checkForSave(pathForCheck1, sizeof(pathForCheck1), pathForCheck1)) { - if (checkForSave(pathForCheck2, sizeof(pathForCheck2), pathForCheck2)) { - DEBUG_FUNCTION_LINE("Redirect save to %s/%s", pathForCheck1, pathForCheck2); - return fallback_function(pathForCheck1, pathForCheck2); - } - } - - FSStatus result = FS_STATUS_OK; - - if (errorMask & FS_ERROR_FLAG_ACCESS_ERROR) { - result = FS_STATUS_ACCESS_ERROR; - } - - return result_handler(result); -} - -FSStatus FSFlushFileWrapper([[maybe_unused]] FSFileHandle handle, FSErrorFlag errorMask, const std::function &result_handler) { - 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; - } - FSStatus result = FS_STATUS_OK; - - if (errorMask & FS_ERROR_FLAG_ACCESS_ERROR) { - result = FS_STATUS_ACCESS_ERROR; - } - - return result_handler(result); -} \ No newline at end of file diff --git a/src/FSWrapper.h b/src/FSWrapper.h deleted file mode 100644 index dcd324c..0000000 --- a/src/FSWrapper.h +++ /dev/null @@ -1,160 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -typedef struct dirMagic { - uint32_t handle{}; - DIR *dir{}; - bool in_use{}; - char path[256]{}; - - OSMutex *mutex{}; - - FSDirectoryEntry *readResult = nullptr; - int readResultCapacity = 0; - int readResultNumberOfEntries = 0; - - FSDirectoryHandle realDirHandle = 0; -} dirMagic_t; - -typedef struct fileMagic { - uint32_t handle; - bool in_use; - int fd; - OSMutex *mutex; -} fileMagic_t; - - -#define ERROR_FLAG_MASK (0xFFFF0000) -#define FORCE_REAL_FUNC_MAGIC (0x42420000) -#define FORCE_REAL_FUNC_WITH_FULL_ERRORS (FORCE_REAL_FUNC_MAGIC | 0x0000FFFF) - -#define HANDLE_INDICATOR_MASK 0xFFFFFF00 -#define HANDLE_INDICATOR_MASK 0xFFFFFF00 -#define HANDLE_MASK (0x000000FF) -#define DIR_HANDLE_MAGIC 0x30000000 -#define FILE_HANDLE_MAGIC 0x30000100 - -#define FILE_HANDLES_LENGTH 64 -#define DIR_HANDLES_LENGTH 64 - -#define FS_STATUS_USE_REAL_OS (FSStatus) 0xFFFF0000 - -extern dirMagic_t dir_handles[DIR_HANDLES_LENGTH]; -extern fileMagic_t file_handles[FILE_HANDLES_LENGTH]; - -FSStatus FSOpenDirWrapper(char *path, - FSDirectoryHandle *handle, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler); - -FSStatus FSReadDirWrapper(FSDirectoryHandle handle, - FSDirectoryEntry *entry, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSCloseDirWrapper(FSDirectoryHandle handle, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSRewindDirWrapper(FSDirectoryHandle handle, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSMakeDirWrapper(char *path, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler); - -FSStatus FSOpenFileWrapper(char *path, - const char *mode, - FSFileHandle *handle, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler); - -FSStatus FSCloseFileWrapper(FSFileHandle handle, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSGetStatWrapper(char *path, - FSStat *stats, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler); - -FSStatus FSGetStatFileWrapper(FSFileHandle handle, - FSStat *stats, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSReadFileWrapper(void *buffer, - uint32_t size, - uint32_t count, - FSFileHandle handle, - uint32_t unk1, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSReadFileWithPosWrapper(void *buffer, - uint32_t size, - uint32_t count, - uint32_t pos, - FSFileHandle handle, - int32_t unk1, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSSetPosFileWrapper(FSFileHandle handle, - uint32_t pos, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSGetPosFileWrapper(FSFileHandle handle, - uint32_t *pos, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSIsEofWrapper(FSFileHandle handle, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSTruncateFileWrapper(FSFileHandle handle, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSWriteFileWrapper(uint8_t *buffer, - uint32_t size, - uint32_t count, - FSFileHandle handle, - uint32_t unk1, - FSErrorFlag errorMask, - const std::function &result_handler); - -FSStatus FSRemoveWrapper(char *path, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler); - -FSStatus FSRenameWrapper(char *oldPath, - char *newPath, - FSErrorFlag errorMask, - const std::function &fallback_function, - const std::function &result_handler); - -FSStatus FSFlushFileWrapper(FSFileHandle handle, - FSErrorFlag errorMask, - const std::function &result_handler); - -int32_t getNewDirHandleIndex(); - -int32_t getNewFileHandleIndex(); - -bool isValidDirHandle(int32_t handle); - -bool isValidFileHandle(int32_t handle); \ No newline at end of file diff --git a/src/FileUtils.cpp b/src/FileUtils.cpp index cca71ec..8d64214 100644 --- a/src/FileUtils.cpp +++ b/src/FileUtils.cpp @@ -1,94 +1,7 @@ #include "FileUtils.h" - -#include -#include -#include -#include - -#include "utils/StringTools.h" #include "utils/logger.h" -#include "utils/utils.h" #include -#include -#include -#include -#include -#include - -extern "C" OSMessageQueue *OSGetDefaultAppIOQueue(); - -FSCmdBlockBody *fsCmdBlockGetBody(FSCmdBlock *cmdBlock) { - if (!cmdBlock) { - return nullptr; - } - - auto body = (FSCmdBlockBody *) (ROUNDUP((uint32_t) cmdBlock, 0x40)); - return body; -} - -FSStatus send_result_async(FSClient *client, FSCmdBlock *block, FSAsyncData *asyncData, FSStatus status) { - if (asyncData->callback != nullptr) { - if (asyncData->ioMsgQueue != nullptr) { - //OSFatal("ERROR: callback and ioMsgQueue both set."); - return FS_STATUS_FATAL_ERROR; - } - // userCallbacks are called in the DefaultAppIOQueue. - asyncData->ioMsgQueue = OSGetDefaultAppIOQueue(); - //DEBUG_FUNCTION_LINE("Force to OSGetDefaultAppIOQueue (%08X)", asyncData->ioMsgQueue); - } - - if (asyncData->ioMsgQueue != nullptr) { -#pragma GCC diagnostic ignored "-Waddress-of-packed-member" - FSAsyncResult *result = &(fsCmdBlockGetBody(block)->asyncResult); - //DEBUG_FUNCTION_LINE("Send result %d to ioMsgQueue (%08X)", status, asyncData->ioMsgQueue); - result->asyncData.callback = asyncData->callback; - result->asyncData.param = asyncData->param; - result->asyncData.ioMsgQueue = asyncData->ioMsgQueue; - memset(&result->ioMsg, 0, sizeof(result->ioMsg)); - result->ioMsg.data = result; - result->ioMsg.type = OS_FUNCTION_TYPE_FS_CMD_ASYNC; - result->client = client; - result->block = block; - result->status = status; - - while (!OSSendMessage(asyncData->ioMsgQueue, (OSMessage *) &(result->ioMsg), OS_MESSAGE_FLAGS_NONE)) { - DEBUG_FUNCTION_LINE("Failed to send message"); - } - } - return FS_STATUS_OK; -} - -int32_t readIntoBuffer(int32_t handle, void *buffer, size_t size, size_t count) { - int32_t sizeToRead = size * count; - /* - // https://github.com/decaf-emu/decaf-emu/blob/131aeb14fccff8461a5fd9f2aa5c040ba3880ef5/src/libdecaf/src/cafe/libraries/coreinit/coreinit_fs_cmd.cpp#L2346 - if (sizeToRead > 0x100000) { - sizeToRead = 0x100000; - }*/ - void *newBuffer = buffer; - int32_t curResult = -1; - int32_t totalSize = 0; - // int32_t toRead = 0; - while (sizeToRead > 0) { - curResult = read(handle, newBuffer, sizeToRead); - if (curResult < 0) { - DEBUG_FUNCTION_LINE("Error: Reading %08X bytes from handle %08X. result %08X errno: %d ", size * count, handle, curResult, errno); - return -1; - } - if (curResult == 0) { - //DEBUG_FUNCTION_LINE("EOF"); - break; - } - newBuffer = (void *) (((uint32_t) newBuffer) + curResult); - totalSize += curResult; - sizeToRead -= curResult; - if (sizeToRead > 0) { - //DEBUG_FUNCTION_LINE("Reading. missing %08X bytes\n", sizeToRead); - } - } - //DEBUG_FUNCTION_LINE("Success: Read %08X bytes from handle %08X. result %08X \n", size * count, handle, totalSize); - return totalSize; -} +#include int32_t CheckFile(const char *filepath) { if (!filepath) { @@ -164,93 +77,4 @@ int32_t CreateSubfolder(const char *fullpath) { } return 1; -} - - -int32_t getRPXInfoForPath(const std::string &path, romfs_fileInfo *info) { - if (romfsMount("rcc", path.c_str(), RomfsSource_FileDescriptor_CafeOS) < 0) { - return -1; - } - DIR *dir; - struct dirent *entry; - - if (!(dir = opendir("rcc:/code/"))) { - romfsUnmount("rcc"); - return -2; - } - bool found = false; - int res = -3; - while ((entry = readdir(dir)) != nullptr) { - if (StringTools::EndsWith(entry->d_name, ".rpx")) { - if (romfsGetFileInfoPerPath("rcc", (std::string("code/") + entry->d_name).c_str(), info) >= 0) { - found = true; - res = 0; - } else { - DEBUG_FUNCTION_LINE("Failed to get info for %s", entry->d_name); - } - break; - } - } - - closedir(dir); - - romfsUnmount("rcc"); - - if (!found) { - return -4; - } - return res; -} - -int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size) { - //! always initialze input - *inbuffer = nullptr; - if (size) { - *size = 0; - } - - int32_t iFd = open(filepath, O_RDONLY); - if (iFd < 0) { - return -1; - } - - uint32_t filesize = lseek(iFd, 0, SEEK_END); - lseek(iFd, 0, SEEK_SET); - - auto *buffer = (uint8_t *) memalign(0x40, ROUNDUP(filesize, 0x40)); - if (buffer == nullptr) { - close(iFd); - return -2; - } - - uint32_t blocksize = 0x20000; - uint32_t done = 0; - int32_t readBytes; - - while (done < filesize) { - if (done + blocksize > filesize) { - blocksize = filesize - done; - } - readBytes = read(iFd, buffer + done, blocksize); - if (readBytes <= 0) - break; - done += readBytes; - } - - ::close(iFd); - - if (done != filesize) { - free(buffer); - buffer = nullptr; - return -3; - } - - *inbuffer = buffer; - - //! sign is optional input - if (size) { - *size = filesize; - } - - return filesize; } \ No newline at end of file diff --git a/src/FileUtils.h b/src/FileUtils.h index 04789ca..95adbef 100644 --- a/src/FileUtils.h +++ b/src/FileUtils.h @@ -1,23 +1,9 @@ #pragma once - #include +#include #include #include -struct WUT_PACKED FSCmdBlockBody { //! FSAsyncResult object used for this command. - - WUT_UNKNOWN_BYTES(0x96C); - FSAsyncResult asyncResult; -}; -WUT_CHECK_OFFSET(FSCmdBlockBody, 0x96C, asyncResult); -WUT_CHECK_SIZE(FSCmdBlockBody, 0x96C + 0x28); - -FSCmdBlockBody *fsCmdBlockGetBody(FSCmdBlock *cmdBlock); - -FSStatus send_result_async(FSClient *client, FSCmdBlock *block, FSAsyncData *asyncData, FSStatus result); - -int32_t readIntoBuffer(int32_t handle, void *buffer, size_t size, size_t count); - int32_t CreateSubfolder(const char *fullpath); int32_t getRPXInfoForPath(const std::string &path, romfs_fileInfo *info); diff --git a/src/RPXLoading.cpp b/src/RPXLoading.cpp index 2887dbf..4d64fb4 100644 --- a/src/RPXLoading.cpp +++ b/src/RPXLoading.cpp @@ -1,21 +1,30 @@ #include "RPXLoading.h" -#include "FileUtils.h" #include "globals.h" #include "utils/FileReader.h" -#include "utils/FileReaderCompressed.h" #include "utils/StringTools.h" #include "utils/ini.h" #include "utils/logger.h" -#include #include +#include #include #include -#include -#include +#include #include #include -#include +#include #include +#include + +std::mutex fileReaderListMutex; +std::vector openFileReaders; + +void RPXLoadingCleanUp() { + const std::lock_guard lock(fileReaderListMutex); + for (auto &reader : openFileReaders) { + delete reader; + } + openFileReaders.clear(); +} /* * Patch the meta xml for the home menu @@ -38,36 +47,54 @@ 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 (gReplacementInfo.rpxReplacementInfo.isRPXReplaced) { - if (StringTools::EndsWith(path, iconTex)) { - auto *reader = new FileReader(reinterpret_cast(gReplacementInfo.rpxReplacementInfo.iconCache), ICON_SIZE); - *handle = (uint32_t) reader; - return FS_STATUS_OK; - } + const char *iconTex = "iconTex.tga"; + std::string_view pathView = path; + if (gReplacementInfo.rpxReplacementInfo.isRPXReplaced && pathView.ends_with(iconTex)) { + const std::lock_guard lock(fileReaderListMutex); + auto *reader = new (std::nothrow) FileReader(reinterpret_cast(gReplacementInfo.rpxReplacementInfo.iconCache), ICON_SIZE); + if (!reader) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory for the FileReader"); + return FS_STATUS_FATAL_ERROR; } + openFileReaders.push_back(reader); + *handle = reinterpret_cast(reader); + return FS_STATUS_OK; } int result = real_RPX_FSOpenFile(client, block, path, mode, handle, error); return result; } DECL_FUNCTION(FSStatus, RPX_FSReadFile, FSClient *client, FSCmdBlock *block, uint8_t *buffer, uint32_t size, uint32_t count, FSFileHandle handle, uint32_t unk1, uint32_t flags) { - // We check if the handle is part of our heap (the MemoryMapping Module allocates to 0x80000000) - if ((handle & 0xF0000000) == 0x80000000) { - auto reader = (FileReader *) handle; - return (FSStatus) reader->read(buffer, size * count); + if (gReplacementInfo.rpxReplacementInfo.isRPXReplaced) { + const std::lock_guard lock(fileReaderListMutex); + for (auto &reader : openFileReaders) { + if ((uint32_t) reader == (uint32_t) handle) { + return (FSStatus) (reader->read(buffer, size * count) / size); + } + } } - FSStatus result = real_RPX_FSReadFile(client, block, buffer, size, count, handle, unk1, flags); - return result; + return real_RPX_FSReadFile(client, block, buffer, size, count, handle, unk1, flags); } DECL_FUNCTION(FSStatus, RPX_FSCloseFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, uint32_t flags) { - // We check if the handle is part of our heap (the MemoryMapping Module allocates to 0x80000000) - if ((handle & 0xF0000000) == 0x80000000) { - auto reader = (FileReader *) handle; - delete reader; - return FS_STATUS_OK; + if (gReplacementInfo.rpxReplacementInfo.isRPXReplaced) { + const std::lock_guard lock(fileReaderListMutex); + bool found = false; + int index = 0; + FileReader *reader = nullptr; + for (auto &cur : openFileReaders) { + if ((uint32_t) cur == (uint32_t) handle) { + found = true; + reader = cur; + break; + } + index++; + } + if (found) { + openFileReaders.erase(openFileReaders.begin() + index); + delete reader; + return FS_STATUS_OK; + } } return real_RPX_FSCloseFile(client, block, handle, flags); @@ -115,63 +142,56 @@ bool RL_LoadFromSDOnNextLaunch(const char *bundle_path) { request.filesize = 0; // unknown filesize request.fileoffset = 0; // - romfs_fileInfo info; + WUHBRPXInfo fileInfo; bool metaLoaded = false; std::string completePath = std::string("/vol/external01/") + bundle_path; - int res = getRPXInfoForPath(completePath, &info); - bool isBundle = false; - if (res >= 0) { - 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) { - uint8_t *buffer = nullptr; - uint32_t size = 0; - if (LoadFileToMem("rcc:/meta/meta.ini", &buffer, &size) >= 0 && size > 0) { - buffer[size - 1] = 0; + bool isBundle = false; + auto rpxInfo = WUHBUtils_GetRPXInfo(completePath.c_str(), BundleSource_FileDescriptor_CafeOS, &fileInfo); + if (rpxInfo == WUHB_UTILS_RESULT_SUCCESS) { + isBundle = true; + request.filesize = ((uint32_t *) &fileInfo.length)[1]; + request.fileoffset = ((uint32_t *) &fileInfo.offset)[1]; + auto res = -1; + + if (WUHBUtils_MountBundle("rcc", completePath.c_str(), BundleSource_FileDescriptor_CafeOS, &res) == WUHB_UTILS_RESULT_SUCCESS && res == 0) { + uint8_t *buffer; + uint32_t bufferSize; + if (WUHBUtils_ReadWholeFile("rcc:/meta/meta.ini", &buffer, &bufferSize) == WUHB_UTILS_RESULT_SUCCESS) { + buffer[bufferSize - 1] = '\0'; if (ini_parse_string((const char *) buffer, parseINIhandler, &gReplacementInfo.rpxReplacementInfo.metaInformation) < 0) { - DEBUG_FUNCTION_LINE("Failed to load and parse meta.ini"); + DEBUG_FUNCTION_LINE_ERR("Failed to load and parse meta.ini"); } else { metaLoaded = true; } - } - if (buffer) { free(buffer); - buffer = nullptr; - } - - FileReader *reader = nullptr; - - if (CheckFile("rcc:/meta/iconTex.tga")) { - std::string path = "rcc:/meta/iconTex.tga"; - reader = new FileReader(path); - } else if (CheckFile("rcc:/meta/iconTex.tga.gz")) { - std::string path = "rcc:/meta/iconTex.tga.gz"; - reader = new FileReaderCompressed(path); - } - if (reader) { - uint32_t alreadyRead = 0; - uint32_t toRead = ICON_SIZE; - do { - int read = reader->read(reinterpret_cast(&gReplacementInfo.rpxReplacementInfo.iconCache[alreadyRead]), toRead); - if (read <= 0) { - break; - } - alreadyRead += read; - toRead -= read; - } while (alreadyRead < ICON_SIZE); - delete reader; } else { - memset(gReplacementInfo.rpxReplacementInfo.iconCache, 0, sizeof(gReplacementInfo.rpxReplacementInfo.iconCache)); + DEBUG_FUNCTION_LINE_ERR("Failed to read whole file meta.ini"); + } + buffer = nullptr; + bufferSize = 0; + + if (WUHBUtils_ReadWholeFile("rcc:/meta/iconTex.tga", &buffer, &bufferSize) == WUHB_UTILS_RESULT_SUCCESS) { + uint32_t cpySize = ICON_SIZE; + if (bufferSize < cpySize) { + cpySize = bufferSize; + memset(gReplacementInfo.rpxReplacementInfo.iconCache, 0, ICON_SIZE); + } + memcpy(gReplacementInfo.rpxReplacementInfo.iconCache, buffer, cpySize); + free(buffer); + } else { + DEBUG_FUNCTION_LINE_ERR("Failed to read iconTex.tga"); + } + + auto outRes = 0; + if (WUHBUtils_UnmountBundle("rcc", &outRes) != WUHB_UTILS_RESULT_SUCCESS || outRes != WUHB_UTILS_RESULT_SUCCESS) { + DEBUG_FUNCTION_LINE_ERR("Failed to unmount bundle"); } - romfsUnmount("rcc"); } } else { - if (!(gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && - gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted)) { + if (!gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) { memset(gReplacementInfo.rpxReplacementInfo.iconCache, 0, sizeof(gReplacementInfo.rpxReplacementInfo.iconCache)); } } @@ -207,7 +227,7 @@ bool RL_LoadFromSDOnNextLaunch(const char *bundle_path) { if (!success) { gReplacementInfo.rpxReplacementInfo.willRPXBeReplaced = false; - DEBUG_FUNCTION_LINE("Failed to load %s on next restart", request.path); + DEBUG_FUNCTION_LINE_ERR("Failed to load %s on next restart", request.path); return false; } else { gReplacementInfo.rpxReplacementInfo.willRPXBeReplaced = true; @@ -215,27 +235,21 @@ bool RL_LoadFromSDOnNextLaunch(const char *bundle_path) { DEBUG_FUNCTION_LINE("Launch %s on next restart [size: %08X offset: %08X]", request.path, request.filesize, request.fileoffset); + gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath[0] = '\0'; if (isBundle) { - DEBUG_FUNCTION_LINE("Loaded file is a .wuhb bundle"); - gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath[0] = '\0'; + DEBUG_FUNCTION_LINE_VERBOSE("Loaded file is a .wuhb bundle"); strncat(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath, completePath.c_str(), sizeof(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath) - 1); - gReplacementInfo.contentReplacementInfo.mode = CONTENTREDIRECT_FROM_WUHB_BUNDLE; - gReplacementInfo.contentReplacementInfo.replaceSave = true; } else { - DEBUG_FUNCTION_LINE("Loaded file is no bundle"); + DEBUG_FUNCTION_LINE_VERBOSE("Loaded file is no bundle"); gReplacementInfo.rpxReplacementInfo.willRPXBeReplaced = true; - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE && - gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) { + if (gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) { // 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) - 2); - } else { - gReplacementInfo.contentReplacementInfo.replaceSave = false; } } @@ -244,99 +258,89 @@ bool RL_LoadFromSDOnNextLaunch(const char *bundle_path) { return true; } -int32_t RL_MountBundle(const char *name, const char *path, BundleSource source) { - return romfsMount(name, path, (RomfsSource) source); -} +std::mutex mutex; -int32_t RL_UnmountBundle(const char *name) { - return romfsUnmount(name); -} - -bool RL_UnmountCurrentRunningBundle() { - if (gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted == false) { - return true; - } - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE) { - if (gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) { - DEBUG_FUNCTION_LINE("Unmount /vol/content"); - romfsUnmount("rom"); - gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false; - OSMemoryBarrier(); - return true; +bool RL_DisableContentRedirection() { + std::lock_guard lock(mutex); + if (contentLayerHandle != 0) { + auto res = ContentRedirection_SetActive(contentLayerHandle, false); + if (res != CONTENT_REDIRECTION_RESULT_SUCCESS) { + return false; } } - return false; -} - -int32_t RL_FileOpen(const char *name, uint32_t *handle) { - if (handle == nullptr) { - return -1; + if (saveLayerHandle != 0) { + auto res = ContentRedirection_SetActive(saveLayerHandle, false); + if (res != CONTENT_REDIRECTION_RESULT_SUCCESS) { + ContentRedirection_SetActive(contentLayerHandle, true); + return false; + } } - - FileReader *reader; - std::string path = std::string(name); - std::string pathGZ = path + ".gz"; - - if (CheckFile(path.c_str())) { - reader = new FileReader(path); - } else if (CheckFile(pathGZ.c_str())) { - reader = new FileReaderCompressed(pathGZ); - } else { - return -2; - } - if (reader == nullptr) { - return -3; - } - *handle = (uint32_t) reader; - return 0; -} - -int32_t RL_FileRead(uint32_t handle, uint8_t *buffer, uint32_t size) { - auto reader = (FileReader *) handle; - return reader->read(buffer, size); -} - -int32_t RL_FileClose(uint32_t handle) { - auto reader = (FileReader *) handle; - delete reader; - return 0; -} - -bool RL_FileExists(const char *name) { - std::string checkgz = std::string(name) + ".gz"; - return CheckFile(name) || CheckFile(checkgz.c_str()); -} - -bool RL_RedirectContentWithFallback(const char *newContentPath) { - auto dirHandle = opendir(newContentPath); - if (dirHandle == nullptr) { - return false; - } - closedir(dirHandle); - - gReplacementInfo.contentReplacementInfo.replacementPath[0] = '\0'; - strncat(gReplacementInfo.contentReplacementInfo.replacementPath, newContentPath, sizeof(gReplacementInfo.contentReplacementInfo.replacementPath) - 1); - gReplacementInfo.contentReplacementInfo.mode = CONTENTREDIRECT_FROM_PATH; - gReplacementInfo.contentReplacementInfo.fallbackOnError = true; - gReplacementInfo.contentReplacementInfo.replaceSave = false; return true; } -bool RL_DisableContentRedirection() { - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) { - gReplacementInfo.contentReplacementInfo.mode = CONTENTREDIRECT_NONE; - return true; +bool RL_EnableContentRedirection() { + std::lock_guard lock(mutex); + if (contentLayerHandle != 0) { + auto res = ContentRedirection_SetActive(contentLayerHandle, true); + if (res != CONTENT_REDIRECTION_RESULT_SUCCESS) { + return false; + } } - return false; + if (saveLayerHandle != 0) { + auto res = ContentRedirection_SetActive(saveLayerHandle, true); + if (res != CONTENT_REDIRECTION_RESULT_SUCCESS) { + ContentRedirection_SetActive(contentLayerHandle, false); + return false; + } + } + return true; } +bool RL_UnmountCurrentRunningBundle() { + std::lock_guard lock(mutex); + if (gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted == false) { + return true; + } + + int outRes = -1; + if (ContentRedirection_RemoveDevice(WUHB_ROMFS_NAME, &outRes) == CONTENT_REDIRECTION_RESULT_SUCCESS) { + if (outRes < 0) { + DEBUG_FUNCTION_LINE_ERR("RemoveDevice \"%s\" failed for ContentRedirection Module", WUHB_ROMFS_NAME); + OSFatal("RL_UnmountCurrentRunningBundle: RemoveDevice \"" WUHB_ROMFS_NAME "\" failed for ContentRedirection Module"); + } + } else { + DEBUG_FUNCTION_LINE_ERR("ContentRedirection_RemoveDevice failed"); + OSFatal("RL_UnmountCurrentRunningBundle: ContentRedirection_RemoveDevice failed"); + } + + bool res = true; + + if (contentLayerHandle != 0) { + if (ContentRedirection_RemoveFSLayer(contentLayerHandle) != CONTENT_REDIRECTION_RESULT_SUCCESS) { + res = false; + } + contentLayerHandle = 0; + } + + if (saveLayerHandle != 0) { + if (ContentRedirection_RemoveFSLayer(saveLayerHandle) != CONTENT_REDIRECTION_RESULT_SUCCESS) { + res = false; + } + saveLayerHandle = 0; + } + + romfsUnmount(WUHB_ROMFS_NAME); + gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false; + OSMemoryBarrier(); + return res; +} + +RPXLoaderVersion RL_GetVersion() { + return RPX_LOADER_MODULE_VERSION; +} + +WUMS_EXPORT_FUNCTION(RL_GetVersion); WUMS_EXPORT_FUNCTION(RL_LoadFromSDOnNextLaunch); -WUMS_EXPORT_FUNCTION(RL_MountBundle); -WUMS_EXPORT_FUNCTION(RL_UnmountBundle); -WUMS_EXPORT_FUNCTION(RL_FileOpen); -WUMS_EXPORT_FUNCTION(RL_FileRead); -WUMS_EXPORT_FUNCTION(RL_FileClose); -WUMS_EXPORT_FUNCTION(RL_FileExists); -WUMS_EXPORT_FUNCTION(RL_RedirectContentWithFallback); +WUMS_EXPORT_FUNCTION(RL_EnableContentRedirection); WUMS_EXPORT_FUNCTION(RL_DisableContentRedirection); WUMS_EXPORT_FUNCTION(RL_UnmountCurrentRunningBundle); \ No newline at end of file diff --git a/src/RPXLoading.h b/src/RPXLoading.h index ccc1b4e..f403a78 100644 --- a/src/RPXLoading.h +++ b/src/RPXLoading.h @@ -18,6 +18,9 @@ typedef struct __attribute((packed)) { extern function_replacement_data_t rpx_utils_function_replacements[]; extern uint32_t rpx_utils_function_replacements_size; +void RPXLoadingCleanUp(); +bool RL_UnmountCurrentRunningBundle(); + #ifdef __cplusplus } #endif diff --git a/src/contentredirection.def b/src/contentredirection.def new file mode 100644 index 0000000..dfb89dc --- /dev/null +++ b/src/contentredirection.def @@ -0,0 +1,4 @@ +:NAME homebrew_content_redirection + +:TEXT +CRGetVersion \ No newline at end of file diff --git a/src/globals.cpp b/src/globals.cpp index 3ba5955..40efb1e 100644 --- a/src/globals.cpp +++ b/src/globals.cpp @@ -1,7 +1,5 @@ #include "globals.h" -#include RPXLoader_ReplacementInformation gReplacementInfo __attribute__((section(".data"))); - -FSClient *gFSClient __attribute__((section(".data"))) = nullptr; -FSCmdBlock *gFSCmd __attribute__((section(".data"))) = nullptr; \ No newline at end of file +CRLayerHandle contentLayerHandle __attribute__((section(".data"))) = 0; +CRLayerHandle saveLayerHandle __attribute__((section(".data"))) = 0; \ No newline at end of file diff --git a/src/globals.h b/src/globals.h index 5cf3a1c..58c87c4 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1,9 +1,14 @@ #include "utils/utils.h" +#include #include #include #include #include +#define WUHB_ROMFS_NAME "wuhbrom" +#define WUHB_ROMFS_PATH WUHB_ROMFS_NAME ":" +#define WUHB_ROMFS_CONTENT_PATH WUHB_ROMFS_PATH "/content" + typedef struct WUT_PACKED MetaInformation_t { char shortname[64]; char longname[64]; @@ -11,7 +16,7 @@ typedef struct WUT_PACKED MetaInformation_t { } MetaInformation; WUT_CHECK_SIZE(MetaInformation_t, 0xC0); -typedef struct BundleMountInformation_t { +typedef struct ContentRedirectionInformation_t { bool isMounted; char toMountPath[255]; char mountedPath[255]; @@ -29,35 +34,22 @@ typedef struct WUT_PACKED RPXReplacementInfo_t { // make sure the iconCache is aligned to 0x40 WUT_CHECK_OFFSET(RPXReplacementInfo, 0x100, iconCache); - -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]; - - bool fallbackOnError; + char replacementPath[0x280]; } ContentReplacementInfo; +typedef struct ContentReplacementWithFallback_t { + char replacementPath[0x280]; +} ContentReplacementWithFallback; + typedef struct RPXLoader_ReplacementInformation_t { RPXReplacementInfo rpxReplacementInfo; ContentReplacementInfo contentReplacementInfo; + ContentReplacementWithFallback contentReplacementWithFallbackInfo; } RPXLoader_ReplacementInformation; - extern RPXLoader_ReplacementInformation gReplacementInfo; -extern FSClient *gFSClient; -extern FSCmdBlock *gFSCmd; \ No newline at end of file + +extern CRLayerHandle contentLayerHandle; +extern CRLayerHandle saveLayerHandle; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 08bbfdf..52b1240 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,60 +1,62 @@ -#include -#include -#include - -#include "FSDirReplacements.h" -#include "FSFileReplacements.h" #include "FileUtils.h" #include "RPXLoading.h" #include "globals.h" #include "utils/StringTools.h" #include "utils/logger.h" +#include +#include #include #include -#include -#include - -#include #include #include +#include +#include +#include +#include WUMS_MODULE_EXPORT_NAME("homebrew_rpx_loader"); WUMS_USE_WUT_DEVOPTAB(); +extern "C" bool CRGetVersion(); +extern "C" bool WUU_GetVersion(); + WUMS_INITIALIZE() { initLogging(); DEBUG_FUNCTION_LINE("Patch functions"); // we only patch static functions, we don't need re-patch them at every launch - FunctionPatcherPatchFunction(fs_file_function_replacements, fs_file_function_replacements_size); - 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"); gReplacementInfo = {}; + // Call this function to make sure the Content Redirection will be loaded before this module is module. + CRGetVersion(); + + // Call this function to make sure the WUHBUtils will be loaded before this module is module. + WUU_GetVersion(); + + // But then use libcontentredirection instead. + ContentRedirectionStatus error; + if ((error = ContentRedirection_Init()) != CONTENT_REDIRECTION_RESULT_SUCCESS) { + DEBUG_FUNCTION_LINE_ERR("Failed to init ContentRedirection. Error %d", error); + OSFatal("Failed to init ContentRedirection."); + } + + // But then use libwuhbutils instead. + WUHBUtilsStatus error2; + if ((error2 = WUHBUtils_Init()) != WUHB_UTILS_RESULT_SUCCESS) { + DEBUG_FUNCTION_LINE_ERR("RPXLoadingModule: Failed to init WUHBUtils. Error %d", error2); + OSFatal("Failed to init WUHBUtils."); + } + deinitLogging(); } - WUMS_APPLICATION_ENDS() { - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) { - gReplacementInfo.contentReplacementInfo.mode = CONTENTREDIRECT_NONE; - } - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE) { - if (gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted) { - DEBUG_FUNCTION_LINE("Unmount /vol/content"); - romfsUnmount("rom"); - gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false; - OSMemoryBarrier(); - } - } + RL_UnmountCurrentRunningBundle(); + gReplacementInfo.rpxReplacementInfo.isRPXReplaced = false; - if (gFSClient) { - FSDelClient(gFSClient, FS_ERROR_FLAG_ALL); - free(gFSClient); - gFSClient = nullptr; - } - free(gFSCmd); - gFSCmd = nullptr; + + RPXLoadingCleanUp(); deinitLogging(); } @@ -70,74 +72,75 @@ WUMS_APPLICATION_STARTS() { gReplacementInfo.rpxReplacementInfo.isRPXReplaced = true; } - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_PATH) { - auto fsClient = (FSClient *) memalign(0x20, sizeof(FSClient)); - auto fsCmd = (FSCmdBlock *) memalign(0x20, sizeof(FSCmdBlock)); + if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) == OSGetTitleID() && + strlen(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath) > 0) { + uint32_t currentHash = StringTools::hash(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath); - if (fsClient == nullptr || fsCmd == nullptr) { - DEBUG_FUNCTION_LINE("Failed to alloc memory for fsclient or fsCmd"); - free(fsClient); - free(fsCmd); - } else { - auto rc = FSAddClient(fsClient, FS_ERROR_FLAG_ALL); - if (rc < 0) { - DEBUG_FUNCTION_LINE("Failed to add FSClient"); - } else { - FSInitCmdBlock(fsCmd); - gFSClient = fsClient; - gFSCmd = fsCmd; - } - } - return; - } + nn::act::Initialize(); + nn::act::PersistentId persistentId = nn::act::GetPersistentId(); + nn::act::Finalize(); - if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) != OSGetTitleID()) { - DEBUG_FUNCTION_LINE("Set mode to CONTENTREDIRECT_NONE and replaceSave to false"); - gReplacementInfo.contentReplacementInfo.mode = CONTENTREDIRECT_NONE; - gReplacementInfo.contentReplacementInfo.replaceSave = false; - OSMemoryBarrier(); - } else { - if (gReplacementInfo.contentReplacementInfo.mode == CONTENTREDIRECT_FROM_WUHB_BUNDLE) { - uint32_t currentHash = StringTools::hash(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath); + std::string basePath = string_format("/vol/external01/wiiu/apps/save/%08X", currentHash); + std::string common = string_format("fs:/vol/external01/wiiu/apps/save/%08X/common", currentHash); + std::string user = string_format("fs:/vol/external01/wiiu/apps/save/%08X/%08X", currentHash, 0x80000000 | persistentId); - nn::act::Initialize(); - nn::act::PersistentId persistentId = nn::act::GetPersistentId(); - nn::act::Finalize(); + CreateSubfolder(common.c_str()); + CreateSubfolder(user.c_str()); + DEBUG_FUNCTION_LINE("Created %s and %s", common.c_str(), user.c_str()); - 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", currentHash); - std::string user = StringTools::strfmt("fs:/vol/external01/wiiu/apps/save/%08X/%08X", currentHash, 0x80000000 | persistentId); - - gReplacementInfo.contentReplacementInfo.savePath[0] = '\0'; - strncat(gReplacementInfo.contentReplacementInfo.savePath, - basePath.c_str(), - sizeof(gReplacementInfo.contentReplacementInfo.savePath) - 1); - - memset(gReplacementInfo.contentReplacementInfo.workingDir, 0, sizeof(gReplacementInfo.contentReplacementInfo.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.contentReplacementInfo.bundleMountInformation.toMountPath, RomfsSource_FileDescriptor_CafeOS) == 0) { - gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath[0] = '\0'; - strncat(gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath, - gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath, - sizeof(gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath) - 1); - - - 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); + if (romfsMount(WUHB_ROMFS_NAME, gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath, RomfsSource_FileDescriptor_CafeOS) == 0) { + auto device = GetDeviceOpTab(WUHB_ROMFS_PATH); + if (device == nullptr || strcmp(device->name, WUHB_ROMFS_NAME) != 0) { + romfsUnmount(WUHB_ROMFS_NAME); gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false; + DEBUG_FUNCTION_LINE_ERR("DeviceOpTab for %s not found.", WUHB_ROMFS_PATH); + return; + } + int outRes = -1; + if (ContentRedirection_AddDevice(device, &outRes) != CONTENT_REDIRECTION_RESULT_SUCCESS || outRes < 0) { + DEBUG_FUNCTION_LINE_ERR("Failed to AddDevice to ContentRedirection"); + romfsUnmount(WUHB_ROMFS_NAME); + gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false; + return; + } + auto res = ContentRedirection_AddFSLayer(&contentLayerHandle, + "WUHB Content", + WUHB_ROMFS_CONTENT_PATH, + FS_LAYER_TYPE_CONTENT_REPLACE); + if (res == CONTENT_REDIRECTION_RESULT_SUCCESS) { + res = ContentRedirection_AddFSLayer(&saveLayerHandle, + "WUHB Save", + basePath.c_str(), + FS_LAYER_TYPE_SAVE_REPLACE); + if (res == CONTENT_REDIRECTION_RESULT_SUCCESS) { + gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath[0] = '\0'; + strncpy(gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath, + gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath, + sizeof(gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath)); + DEBUG_FUNCTION_LINE_VERBOSE("Mounted %s to /vol/content", gReplacementInfo.contentReplacementInfo.bundleMountInformation.mountedPath); + gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = true; + gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath[0] = '\0'; + + OSMemoryBarrier(); + return; + } else { + if (contentLayerHandle != 0) { + ContentRedirection_RemoveFSLayer(contentLayerHandle); + contentLayerHandle = 0; + } + DEBUG_FUNCTION_LINE_ERR("ContentRedirection_AddFSLayer had failed for save"); + } + } else { + int outRes = -1; + if (ContentRedirection_RemoveDevice(WUHB_ROMFS_PATH, &outRes) != CONTENT_REDIRECTION_RESULT_SUCCESS || res < 0) { + DEBUG_FUNCTION_LINE_ERR("Failed to remove device"); + } + romfsUnmount(WUHB_ROMFS_PATH); + DEBUG_FUNCTION_LINE_ERR("ContentRedirection_AddFSLayer had failed for content"); } } - + DEBUG_FUNCTION_LINE_ERR("Failed to mount %s", gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath); + gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false; OSMemoryBarrier(); } } diff --git a/src/utils/FileReader.cpp b/src/utils/FileReader.cpp index 04d4b52..1924d10 100644 --- a/src/utils/FileReader.cpp +++ b/src/utils/FileReader.cpp @@ -2,7 +2,7 @@ #include "logger.h" #include -int FileReader::read(uint8_t *buffer, uint32_t size) { +int64_t FileReader::read(uint8_t *buffer, uint32_t size) { if (isReadFromBuffer) { if (input_buffer == nullptr) { return -1; @@ -31,7 +31,7 @@ FileReader::FileReader(std::string &path) { this->isReadFromBuffer = false; this->file_fd = fd; } else { - DEBUG_FUNCTION_LINE("Failed to open file %s", path.c_str()); + DEBUG_FUNCTION_LINE_ERR("Failed to open file %s", path.c_str()); } } diff --git a/src/utils/FileReader.h b/src/utils/FileReader.h index 19fe6ec..0af542b 100644 --- a/src/utils/FileReader.h +++ b/src/utils/FileReader.h @@ -15,7 +15,7 @@ public: virtual ~FileReader(); - virtual int read(uint8_t *buffer, uint32_t size); + virtual int64_t read(uint8_t *buffer, uint32_t size); private: bool isReadFromBuffer = false; @@ -24,5 +24,5 @@ private: uint32_t input_pos = 0; bool isReadFromFile = false; - int file_fd = 0; + int file_fd = -1; }; diff --git a/src/utils/FileReaderCompressed.cpp b/src/utils/FileReaderCompressed.cpp deleted file mode 100644 index a25558e..0000000 --- a/src/utils/FileReaderCompressed.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "FileReaderCompressed.h" - -int FileReaderCompressed::read(uint8_t *buffer, uint32_t size) { - if (!initDone) { - return -11; - } - int startValue = this->strm.total_out; - uint32_t newSize = 0; - int ret = 0; - do { - uint32_t nextOut = BUFFER_SIZE; - if (nextOut > size) { - nextOut = size; - } - if (this->strm.avail_in == 0) { - int read_res = FileReader::read(this->zlib_in_buf, BUFFER_SIZE); - if (read_res <= 0) { - break; - } - this->strm.avail_in = read_res; - this->strm.next_in = this->zlib_in_buf; - } - /* run inflate() on input until output buffer not full */ - do { - if (nextOut > size - newSize) { - nextOut = size - newSize; - } - - this->strm.avail_out = nextOut; - this->strm.next_out = buffer + newSize; - ret = inflate(&this->strm, Z_NO_FLUSH); - - if (ret == Z_STREAM_ERROR) { - DEBUG_FUNCTION_LINE("Z_STREAM_ERROR"); - return 0; - } - - switch (ret) { - case Z_NEED_DICT: - DEBUG_FUNCTION_LINE("Z_NEED_DICT"); - ret = Z_DATA_ERROR; - [[fallthrough]]; /* and fall through */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - DEBUG_FUNCTION_LINE("Z_MEM_ERROR or Z_DATA_ERROR"); - (void) inflateEnd(&this->strm); - return ret; - default: - break; - } - - newSize = this->strm.total_out - startValue; - if (newSize == size) { - break; - } - nextOut = BUFFER_SIZE; - if (newSize + nextOut >= (size)) { - nextOut = (size) -newSize; - } - } while (this->strm.avail_out == 0 && newSize < (size)); - - /* done when inflate() says it's done */ - } while (ret != Z_STREAM_END && newSize < size); - - return newSize; -} - -FileReaderCompressed::FileReaderCompressed(std::string &file) : FileReader(file) { - this->initCompressedData(); -} - -void FileReaderCompressed::initCompressedData() { - /* allocate inflate state */ - this->strm.zalloc = Z_NULL; - this->strm.zfree = Z_NULL; - this->strm.opaque = Z_NULL; - this->strm.avail_in = 0; - this->strm.next_in = Z_NULL; - int ret = inflateInit2(&this->strm, MAX_WBITS | 16); //gzip - if (ret != Z_OK) { - DEBUG_FUNCTION_LINE("inflateInit2 failed"); - return; - } - initDone = true; -} - -FileReaderCompressed::FileReaderCompressed(uint8_t *buffer, uint32_t size) : FileReader(buffer, size) { - this->initCompressedData(); -} \ No newline at end of file diff --git a/src/utils/FileReaderCompressed.h b/src/utils/FileReaderCompressed.h deleted file mode 100644 index ab2e900..0000000 --- a/src/utils/FileReaderCompressed.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "FileReader.h" -#include "logger.h" -#include - -#define BUFFER_SIZE 0x20000 - -class FileReaderCompressed : public FileReader { -public: - FileReaderCompressed(uint8_t *buffer, uint32_t size); - - explicit FileReaderCompressed(std::string &file); - - ~FileReaderCompressed() override = default; - - int read(uint8_t *buffer, uint32_t size) override; - -private: - bool initDone = false; - alignas(0x40) uint8_t zlib_in_buf[BUFFER_SIZE]{}; - z_stream strm{}; - - void initCompressedData(); -}; diff --git a/src/utils/StringTools.cpp b/src/utils/StringTools.cpp index 7e18248..703a909 100644 --- a/src/utils/StringTools.cpp +++ b/src/utils/StringTools.cpp @@ -1,303 +1,14 @@ -/*************************************************************************** - * Copyright (C) 2010 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - * for WiiXplorer 2010 - ***************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -BOOL StringTools::EndsWith(const std::string &a, const std::string &b) { - if (b.size() > a.size()) { - return false; - } - return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin()); -} - -const char *StringTools::byte_to_binary(int32_t x) { - static char b[9]; - b[0] = '\0'; - - int32_t z; - for (z = 128; z > 0; z >>= 1) { - strcat(b, ((x & z) == z) ? "1" : "0"); - } - - return b; -} - -std::string StringTools::removeCharFromString(std::string &input, char toBeRemoved) { - std::string output = input; - size_t position; - while (1) { - position = output.find(toBeRemoved); - if (position == std::string::npos) - break; - output.erase(position, 1); - } - return output; -} - -const char *StringTools::fmt(const char *format, ...) { - static char strChar[512]; - strChar[0] = 0; - - va_list va; - va_start(va, format); - if ((vsprintf(strChar, format, va) >= 0)) { - va_end(va); - return (const char *) strChar; - } - va_end(va); - - return NULL; -} - -const wchar_t *StringTools::wfmt(const char *format, ...) { - static char tmp[512]; - static wchar_t strWChar[512]; - strWChar[0] = 0; - tmp[0] = 0; - - if (!format) - return (const wchar_t *) strWChar; - - if (strcmp(format, "") == 0) - return (const wchar_t *) strWChar; - - va_list va; - va_start(va, format); - if ((vsprintf(tmp, format, va) >= 0)) { - int bt; - int32_t strlength = strlen(tmp); - bt = mbstowcs(strWChar, tmp, (strlength < 512) ? strlength : 512); - - if (bt > 0) { - strWChar[bt] = 0; - return (const wchar_t *) strWChar; - } - } - va_end(va); - - return NULL; -} - -int32_t StringTools::strprintf(std::string &str, const char *format, ...) { - static char tmp[512]; - tmp[0] = 0; - int32_t result = 0; - - va_list va; - va_start(va, format); - if ((vsprintf(tmp, format, va) >= 0)) { - str = tmp; - result = str.size(); - } - va_end(va); - - return result; -} - -std::string StringTools::strfmt(const char *format, ...) { - std::string str; - static char tmp[512]; - tmp[0] = 0; - - va_list va; - va_start(va, format); - if ((vsprintf(tmp, format, va) >= 0)) { - str = tmp; - } - va_end(va); - - return str; -} - -BOOL StringTools::char2wchar_t(const char *strChar, wchar_t *dest) { - if (!strChar || !dest) - return false; - - int bt; - bt = mbstowcs(dest, strChar, strlen(strChar)); - if (bt > 0) { - dest[bt] = 0; - return true; - } - - return false; -} - -int32_t StringTools::strtokcmp(const char *string, const char *compare, const char *separator) { - if (!string || !compare) - return -1; - - char TokCopy[512]; - strncpy(TokCopy, compare, sizeof(TokCopy)); - TokCopy[511] = '\0'; - - char *strTok = strtok(TokCopy, separator); - - while (strTok != NULL) { - if (strcasecmp(string, strTok) == 0) { - return 0; - } - strTok = strtok(NULL, separator); - } - - return -1; -} - -int32_t StringTools::strextcmp(const char *string, const char *extension, char seperator) { - if (!string || !extension) - return -1; - - char *ptr = strrchr(string, seperator); - if (!ptr) - return -1; - - return strcasecmp(ptr + 1, extension); -} - - -std::vector StringTools::stringSplit(const std::string &inValue, const std::string &splitter) { - std::string value = inValue; - std::vector result; - while (true) { - uint32_t index = value.find(splitter); - if (index == std::string::npos) { - result.push_back(value); - break; - } - std::string first = value.substr(0, index); - result.push_back(first); - if (index + splitter.size() == value.length()) { - result.push_back(""); - break; - } - if (index + splitter.size() > value.length()) { - break; - } - value = value.substr(index + splitter.size(), value.length()); - } - return result; -} - - -const char *StringTools::FullpathToFilename(const char *path) { - if (!path) - return path; - - const char *ptr = path; - const char *Filename = ptr; - - while (*ptr != '\0') { - if (ptr[0] == '/' && ptr[1] != '\0') - Filename = ptr + 1; - - ++ptr; - } - - return Filename; -} - -void StringTools::RemoveDoubleSlashs(std::string &str) { - uint32_t length = str.size(); - - //! clear path of double slashes - for (uint32_t i = 1; i < length; ++i) { - if (str[i - 1] == '/' && str[i] == '/') { - str.erase(i, 1); - i--; - length--; - } - } -} - - -// You must free the result if result is non-NULL. -char *StringTools::str_replace(char *orig, char *rep, char *with) { - char *result; // the return string - char *ins; // the next insert point - char *tmp; // varies - int len_rep; // length of rep (the string to remove) - int len_with; // length of with (the string to replace rep with) - int len_front; // distance between rep and end of last rep - int count; // number of replacements - - // sanity checks and initialization - if (!orig || !rep) - return nullptr; - len_rep = strlen(rep); - if (len_rep == 0) - return nullptr; // empty rep causes infinite loop during count - if (!with) - with = (char *) ""; - len_with = strlen(with); - - // count the number of replacements needed - ins = orig; - for (count = 0; (tmp = strstr(ins, rep)); ++count) { - ins = tmp + len_rep; - } - - tmp = result = (char *) malloc(strlen(orig) + (len_with - len_rep) * count + 1); - - if (!result) - return NULL; - - // first time through the loop, all the variable are set correctly - // from here on, - // tmp points to the end of the result string - // ins points to the next occurrence of rep in orig - // orig points to the remainder of orig after "end of rep" - while (count--) { - ins = strstr(orig, rep); - len_front = ins - orig; - tmp = strncpy(tmp, orig, len_front) + len_front; - tmp = strcpy(tmp, with) + len_with; - orig += len_front + len_rep; // move to next "end of rep" - } - strcpy(tmp, orig); - return result; -} - - -/* hash: compute hash value of string */ -uint32_t StringTools::hash(char *str) { - unsigned int h; - unsigned char *p; - - h = 0; - for (p = (unsigned char *) str; *p != '\0'; p++) { - h = 37 * h + *p; - } - return h; // or, h % ARRAY_SIZE; -} +#include +#include + +/* hash: compute hash value of string */ +uint32_t StringTools::hash(char *str) { + unsigned int h; + unsigned char *p; + + h = 0; + for (p = (unsigned char *) str; *p != '\0'; p++) { + h = 37 * h + *p; + } + return h; // or, h % ARRAY_SIZE; +} diff --git a/src/utils/StringTools.h b/src/utils/StringTools.h index 6bc6e22..a6ef4db 100644 --- a/src/utils/StringTools.h +++ b/src/utils/StringTools.h @@ -1,66 +1,21 @@ -/*************************************************************************** - * Copyright (C) 2010 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - * for WiiXplorer 2010 - ***************************************************************************/ -#ifndef __STRING_TOOLS_H -#define __STRING_TOOLS_H - -#include -#include -#include - -class StringTools { -public: - static BOOL EndsWith(const std::string &a, const std::string &b); - - static const char *byte_to_binary(int32_t x); - - static std::string removeCharFromString(std::string &input, char toBeRemoved); - - static const char *fmt(const char *format, ...); - - static const wchar_t *wfmt(const char *format, ...); - - static int32_t strprintf(std::string &str, const char *format, ...); - - static std::string strfmt(const char *format, ...); - - static BOOL char2wchar_t(const char *src, wchar_t *dest); - - static int32_t strtokcmp(const char *string, const char *compare, const char *separator); - - static int32_t strextcmp(const char *string, const char *extension, char seperator); - - static char *str_replace(char *orig, char *rep, char *with); - - static const char *FullpathToFilename(const char *path); - - static void RemoveDoubleSlashs(std::string &str); - - static std::vector stringSplit(const std::string &value, const std::string &splitter); - - static uint32_t hash(char *str); -}; - -#endif /* __STRING_TOOLS_H */ +#pragma once + +#include "logger.h" +#include +#include +#include +#include + +template +std::string string_format(const std::string &format, Args... args) { + int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0' + auto size = static_cast(size_s); + auto buf = std::make_unique(size); + std::snprintf(buf.get(), size, format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside +} + +class StringTools { +public: + static uint32_t hash(char *str); +}; \ No newline at end of file diff --git a/src/utils/logger.h b/src/utils/logger.h index 847975a..fbefdad 100644 --- a/src/utils/logger.h +++ b/src/utils/logger.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -7,12 +8,21 @@ extern "C" { #endif +#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__) + +// #define VERBOSE_DEBUG + #ifdef DEBUG -#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) -#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__) - +#ifdef VERBOSE_DEBUG +#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) \ + do { \ + WHBLogPrintf("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \ + } while (0) +#else #define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0) +#endif #define DEBUG_FUNCTION_LINE(FMT, ARGS...) \ do { \ @@ -34,6 +44,11 @@ extern "C" { #endif +#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) \ + do { \ + OSReport("## ERROR ## [%23s]%30s@L%04d: ##ERROR## " FMT "\n", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \ + } while (0) + void initLogging(); void deinitLogging(); diff --git a/src/wuhbutils.def b/src/wuhbutils.def new file mode 100644 index 0000000..8b36e94 --- /dev/null +++ b/src/wuhbutils.def @@ -0,0 +1,4 @@ +:NAME homebrew_wuhb_utils + +:TEXT +WUU_GetVersion \ No newline at end of file