mirror of
https://github.com/wiiu-env/RPXLoadingModule.git
synced 2024-11-05 18:05:06 +01:00
172 lines
7.8 KiB
C++
172 lines
7.8 KiB
C++
#include "FileUtils.h"
|
|
#include "RPXLoading.h"
|
|
#include "globals.h"
|
|
#include "utils/StringTools.h"
|
|
#include "utils/logger.h"
|
|
#include "version.h"
|
|
#include <content_redirection/redirection.h>
|
|
#include <coreinit/cache.h>
|
|
#include <coreinit/debug.h>
|
|
#include <coreinit/title.h>
|
|
#include <mocha/mocha.h>
|
|
#include <nn/act.h>
|
|
#include <romfs_dev.h>
|
|
#include <string>
|
|
#include <sysapp/title.h>
|
|
#include <wuhb_utils/utils.h>
|
|
#include <wums.h>
|
|
|
|
#define VERSION "v0.3"
|
|
|
|
WUMS_MODULE_EXPORT_NAME("homebrew_rpx_loader");
|
|
WUMS_USE_WUT_DEVOPTAB();
|
|
|
|
extern "C" ContentRedirectionApiErrorType CRGetVersion(ContentRedirectionVersion *);
|
|
extern "C" WUHBUtilsApiErrorType WUU_GetVersion(WUHBUtilsVersion *);
|
|
|
|
WUMS_INITIALIZE() {
|
|
initLogging();
|
|
DEBUG_FUNCTION_LINE("Patch functions");
|
|
for (uint32_t i = 0; i < rpx_utils_function_replacements_size; i++) {
|
|
if (!FunctionPatcherPatchFunction(&rpx_utils_function_replacements[i], nullptr)) {
|
|
OSFatal("homebrew_rpx_loader: Failed to patch function");
|
|
}
|
|
}
|
|
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(nullptr);
|
|
|
|
// Call this function to make sure the WUHBUtils will be loaded before this module is module.
|
|
WUU_GetVersion(nullptr);
|
|
|
|
// But then use libcontentredirection instead.
|
|
ContentRedirectionStatus error;
|
|
if ((error = ContentRedirection_InitLibrary()) != 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_InitLibrary()) != WUHB_UTILS_RESULT_SUCCESS) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to init WUHBUtils. Error %d", error2);
|
|
OSFatal("Failed to init WUHBUtils.");
|
|
}
|
|
|
|
|
|
// 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");
|
|
}
|
|
|
|
deinitLogging();
|
|
}
|
|
|
|
WUMS_APPLICATION_ENDS() {
|
|
RL_UnmountCurrentRunningBundle();
|
|
|
|
gReplacementInfo.rpxReplacementInfo.isRPXReplaced = false;
|
|
|
|
RPXLoadingCleanUp();
|
|
|
|
deinitLogging();
|
|
}
|
|
|
|
WUMS_APPLICATION_STARTS() {
|
|
uint32_t upid = OSGetUPID();
|
|
if (upid != 2 && upid != 15) {
|
|
return;
|
|
}
|
|
OSReport("Running RPXLoadingModule " VERSION VERSION_EXTRA "\n");
|
|
initLogging();
|
|
if (gReplacementInfo.rpxReplacementInfo.willRPXBeReplaced) {
|
|
gReplacementInfo.rpxReplacementInfo.willRPXBeReplaced = false;
|
|
gReplacementInfo.rpxReplacementInfo.isRPXReplaced = true;
|
|
}
|
|
|
|
if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) != OSGetTitleID()) {
|
|
gReplacementInfo.lastFileLoaded[0] = '\0';
|
|
}
|
|
|
|
if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) == OSGetTitleID() &&
|
|
strlen(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath) > 0) {
|
|
uint32_t currentHash = StringTools::hash(gReplacementInfo.contentReplacementInfo.bundleMountInformation.toMountPath);
|
|
std::string shortNameSanitized = sanitizeName(gReplacementInfo.rpxReplacementInfo.metaInformation.shortname);
|
|
|
|
nn::act::Initialize();
|
|
nn::act::PersistentId persistentId = nn::act::GetPersistentId();
|
|
nn::act::Finalize();
|
|
|
|
std::string basePath = string_format("fs:/vol/external01/wiiu/apps/save/%08X", currentHash);
|
|
if (!shortNameSanitized.empty()) {
|
|
basePath += string_format(" (%s)", shortNameSanitized.c_str());
|
|
}
|
|
|
|
std::string common = basePath + "/common";
|
|
std::string user = basePath + string_format("/%08X", 0x80000000 | persistentId);
|
|
|
|
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);
|
|
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();
|
|
}
|
|
}
|