2021-01-01 01:39:28 +01:00
|
|
|
#include "FileUtils.h"
|
2021-01-17 13:57:57 +01:00
|
|
|
#include "RPXLoading.h"
|
2022-02-04 16:35:35 +01:00
|
|
|
#include "globals.h"
|
|
|
|
#include "utils/StringTools.h"
|
|
|
|
#include "utils/logger.h"
|
2022-10-09 13:06:03 +02:00
|
|
|
#include "version.h"
|
2022-03-12 21:21:21 +01:00
|
|
|
#include <content_redirection/redirection.h>
|
|
|
|
#include <coreinit/cache.h>
|
2022-02-04 16:35:35 +01:00
|
|
|
#include <coreinit/debug.h>
|
|
|
|
#include <coreinit/title.h>
|
2022-08-24 14:36:20 +02:00
|
|
|
#include <mocha/mocha.h>
|
2021-01-17 13:57:57 +01:00
|
|
|
#include <nn/act.h>
|
2022-02-04 16:35:35 +01:00
|
|
|
#include <romfs_dev.h>
|
2022-03-12 21:21:21 +01:00
|
|
|
#include <string>
|
|
|
|
#include <sysapp/title.h>
|
|
|
|
#include <wuhb_utils/utils.h>
|
|
|
|
#include <wums.h>
|
2021-01-01 01:39:28 +01:00
|
|
|
|
2023-02-19 18:38:52 +01:00
|
|
|
#define VERSION "v0.3.2"
|
2022-10-09 13:06:03 +02:00
|
|
|
|
2021-01-01 01:39:28 +01:00
|
|
|
WUMS_MODULE_EXPORT_NAME("homebrew_rpx_loader");
|
2021-09-24 17:15:04 +02:00
|
|
|
WUMS_USE_WUT_DEVOPTAB();
|
|
|
|
|
2023-01-07 16:11:12 +01:00
|
|
|
WUMS_DEPENDS_ON(homebrew_content_redirection);
|
|
|
|
WUMS_DEPENDS_ON(homebrew_wuhb_utils);
|
|
|
|
WUMS_DEPENDS_ON(homebrew_functionpatcher);
|
2022-03-12 21:21:21 +01:00
|
|
|
|
2021-01-24 15:45:30 +01:00
|
|
|
WUMS_INITIALIZE() {
|
2022-01-26 14:25:34 +01:00
|
|
|
initLogging();
|
2023-01-07 16:17:29 +01:00
|
|
|
|
|
|
|
if (FunctionPatcher_InitLibrary() != FUNCTION_PATCHER_RESULT_SUCCESS) {
|
|
|
|
OSFatal("homebrew_rpx_loader: FunctionPatcher_InitLibrary failed");
|
|
|
|
}
|
|
|
|
|
2021-01-01 01:39:28 +01:00
|
|
|
DEBUG_FUNCTION_LINE("Patch functions");
|
2022-05-08 19:31:18 +02:00
|
|
|
for (uint32_t i = 0; i < rpx_utils_function_replacements_size; i++) {
|
2023-01-07 16:17:29 +01:00
|
|
|
bool wasPatched = false;
|
|
|
|
if (FunctionPatcher_AddFunctionPatch(&rpx_utils_function_replacements[i], nullptr, &wasPatched) != FUNCTION_PATCHER_RESULT_SUCCESS || !wasPatched) {
|
2022-05-08 19:31:18 +02:00
|
|
|
OSFatal("homebrew_rpx_loader: Failed to patch function");
|
|
|
|
}
|
|
|
|
}
|
2021-01-01 01:39:28 +01:00
|
|
|
DEBUG_FUNCTION_LINE("Patch functions finished");
|
2021-02-19 20:32:44 +01:00
|
|
|
gReplacementInfo = {};
|
2022-01-26 14:25:34 +01:00
|
|
|
|
2022-03-12 21:21:21 +01:00
|
|
|
ContentRedirectionStatus error;
|
2022-09-04 14:43:42 +02:00
|
|
|
if ((error = ContentRedirection_InitLibrary()) != CONTENT_REDIRECTION_RESULT_SUCCESS) {
|
2022-03-12 21:21:21 +01:00
|
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to init ContentRedirection. Error %d", error);
|
|
|
|
OSFatal("Failed to init ContentRedirection.");
|
2021-04-05 19:54:50 +02:00
|
|
|
}
|
2022-03-12 21:21:21 +01:00
|
|
|
|
|
|
|
WUHBUtilsStatus error2;
|
2022-09-04 14:43:42 +02:00
|
|
|
if ((error2 = WUHBUtils_InitLibrary()) != WUHB_UTILS_RESULT_SUCCESS) {
|
|
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to init WUHBUtils. Error %d", error2);
|
2022-03-12 21:21:21 +01:00
|
|
|
OSFatal("Failed to init WUHBUtils.");
|
2021-01-01 01:39:28 +01:00
|
|
|
}
|
2022-03-12 21:21:21 +01:00
|
|
|
|
2022-08-24 14:36:20 +02:00
|
|
|
|
|
|
|
// Init libmocha
|
|
|
|
MochaUtilsStatus error3;
|
|
|
|
if ((error3 = Mocha_InitLibrary()) != MOCHA_RESULT_SUCCESS) {
|
|
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to init libmocha. Error %s", Mocha_GetStatusStr(error3));
|
|
|
|
OSFatal("Failed to init libmocha. Make sure to use the latest version of MochaPayload");
|
|
|
|
}
|
|
|
|
|
2022-03-12 21:21:21 +01:00
|
|
|
deinitLogging();
|
|
|
|
}
|
|
|
|
|
|
|
|
WUMS_APPLICATION_ENDS() {
|
|
|
|
RL_UnmountCurrentRunningBundle();
|
|
|
|
|
2021-04-13 20:14:50 +02:00
|
|
|
gReplacementInfo.rpxReplacementInfo.isRPXReplaced = false;
|
2022-03-12 21:21:21 +01:00
|
|
|
|
|
|
|
RPXLoadingCleanUp();
|
2022-01-26 14:25:34 +01:00
|
|
|
|
|
|
|
deinitLogging();
|
2021-01-01 01:39:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
WUMS_APPLICATION_STARTS() {
|
|
|
|
uint32_t upid = OSGetUPID();
|
|
|
|
if (upid != 2 && upid != 15) {
|
|
|
|
return;
|
|
|
|
}
|
2022-10-09 13:06:03 +02:00
|
|
|
OSReport("Running RPXLoadingModule " VERSION VERSION_EXTRA "\n");
|
2022-01-26 14:25:34 +01:00
|
|
|
initLogging();
|
2021-04-13 20:14:50 +02:00
|
|
|
if (gReplacementInfo.rpxReplacementInfo.willRPXBeReplaced) {
|
|
|
|
gReplacementInfo.rpxReplacementInfo.willRPXBeReplaced = false;
|
2022-02-04 16:35:35 +01:00
|
|
|
gReplacementInfo.rpxReplacementInfo.isRPXReplaced = true;
|
2021-04-13 20:14:50 +02:00
|
|
|
}
|
2022-01-26 14:25:34 +01:00
|
|
|
|
2022-09-05 20:07:16 +02:00
|
|
|
if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) != OSGetTitleID()) {
|
|
|
|
gReplacementInfo.lastFileLoaded[0] = '\0';
|
|
|
|
}
|
|
|
|
|
2022-03-12 21:21:21 +01:00
|
|
|
if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) == OSGetTitleID() &&
|
|
|
|
strlen(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath) > 0) {
|
2022-10-08 20:53:11 +02:00
|
|
|
uint32_t currentHash = StringTools::hash(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath);
|
|
|
|
std::string shortNameSanitized = sanitizeName(gReplacementInfo.rpxReplacementInfo.metaInformation.shortname);
|
2021-04-05 19:54:50 +02:00
|
|
|
|
2022-03-12 21:21:21 +01:00
|
|
|
nn::act::Initialize();
|
|
|
|
nn::act::PersistentId persistentId = nn::act::GetPersistentId();
|
|
|
|
nn::act::Finalize();
|
|
|
|
|
2022-08-09 16:16:18 +02:00
|
|
|
std::string basePath = string_format("fs:/vol/external01/wiiu/apps/save/%08X", currentHash);
|
2022-10-08 20:53:11 +02:00
|
|
|
if (!shortNameSanitized.empty()) {
|
|
|
|
basePath += string_format(" (%s)", shortNameSanitized.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string common = basePath + "/common";
|
|
|
|
std::string user = basePath + string_format("/%08X", 0x80000000 | persistentId);
|
2022-03-12 21:21:21 +01:00
|
|
|
|
|
|
|
CreateSubfolder(common.c_str());
|
|
|
|
CreateSubfolder(user.c_str());
|
|
|
|
DEBUG_FUNCTION_LINE("Created %s and %s", common.c_str(), user.c_str());
|
|
|
|
|
|
|
|
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);
|
2021-04-05 19:54:50 +02:00
|
|
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false;
|
2022-03-12 21:21:21 +01:00
|
|
|
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");
|
2021-01-01 01:39:28 +01:00
|
|
|
}
|
|
|
|
}
|
2022-03-12 21:21:21 +01:00
|
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to mount %s", gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath);
|
|
|
|
gReplacementInfo.contentReplacementInfo.bundleMountInformation.isMounted = false;
|
2022-02-13 17:33:46 +01:00
|
|
|
OSMemoryBarrier();
|
2021-01-01 01:39:28 +01:00
|
|
|
}
|
|
|
|
}
|