Adapt to new WUPS hooks.

This commit is contained in:
Maschell 2019-11-16 15:12:30 +01:00
parent 73640c01f5
commit 8b6f465892
7 changed files with 110 additions and 84 deletions

View File

@ -3,7 +3,7 @@
replacement_data_t gbl_replacement_data __attribute__((section(".data"))); replacement_data_t gbl_replacement_data __attribute__((section(".data")));
dyn_linking_relocation_data_t gbl_dyn_linking_data __attribute__((section(".data"))); dyn_linking_relocation_data_t gbl_dyn_linking_data __attribute__((section(".data")));
uint8_t gAppStatus __attribute__((section(".data"))) = 0; bool gInBackground __attribute__((section(".data"))) = false;
bool g_NotInLoader __attribute__((section(".data"))) = true; bool g_NotInLoader __attribute__((section(".data"))) = true;
uint64_t gGameTitleID __attribute__((section(".data"))) = 0; uint64_t gGameTitleID __attribute__((section(".data"))) = 0;
volatile uint8_t gSDInitDone __attribute__((section(".data"))) = 0; volatile uint8_t gSDInitDone __attribute__((section(".data"))) = 0;

View File

@ -10,7 +10,7 @@ extern dyn_linking_relocation_data_t gbl_dyn_linking_data;
extern bool g_NotInLoader; extern bool g_NotInLoader;
extern uint8_t gAppStatus; extern bool gInBackground;
extern uint64_t gGameTitleID; extern uint64_t gGameTitleID;
extern volatile uint8_t gSDInitDone; extern volatile uint8_t gSDInitDone;

View File

@ -11,6 +11,7 @@
#include "utils/ConfigUtils.h" #include "utils/ConfigUtils.h"
#include "utils/function_patcher.h" #include "utils/function_patcher.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "utils/mem_utils.h"
#include "utils/ipc.h" #include "utils/ipc.h"
#include "utils.h" #include "utils.h"
#include "system/CThread.h" #include "system/CThread.h"
@ -79,7 +80,7 @@ void ApplyPatchesAndCallHookStartingApp() {
PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static); PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static);
PatchInvidualMethodHooks(method_hooks_hooks, method_hooks_size_hooks, method_calls_hooks); PatchInvidualMethodHooks(method_hooks_hooks, method_hooks_size_hooks, method_calls_hooks);
for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) { for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) {
CallHookEx(WUPS_LOADER_HOOK_STARTING_APPLICATION,plugin_index); CallHookEx(WUPS_LOADER_HOOK_APPLICATION_START,plugin_index);
new_PatchInvidualMethodHooks(&gbl_replacement_data.plugin_data[plugin_index]); new_PatchInvidualMethodHooks(&gbl_replacement_data.plugin_data[plugin_index]);
CallHookEx(WUPS_LOADER_HOOK_FUNCTIONS_PATCHED,plugin_index); CallHookEx(WUPS_LOADER_HOOK_FUNCTIONS_PATCHED,plugin_index);
} }
@ -87,7 +88,6 @@ void ApplyPatchesAndCallHookStartingApp() {
void RestorePatches() { void RestorePatches() {
for(int32_t plugin_index=gbl_replacement_data.number_used_plugins-1; plugin_index>=0; plugin_index--) { for(int32_t plugin_index=gbl_replacement_data.number_used_plugins-1; plugin_index>=0; plugin_index--) {
DEBUG_FUNCTION_LINE("Restoring function for plugin: %d\n",plugin_index);
new_RestoreInvidualInstructions(&gbl_replacement_data.plugin_data[plugin_index]); new_RestoreInvidualInstructions(&gbl_replacement_data.plugin_data[plugin_index]);
} }
RestoreInvidualInstructions(method_hooks_hooks, method_hooks_size_hooks); RestoreInvidualInstructions(method_hooks_hooks, method_hooks_size_hooks);
@ -95,15 +95,14 @@ void RestorePatches() {
} }
void RestoreEverything() { void RestoreEverything() {
CallHook(WUPS_LOADER_HOOK_RELEASE_FOREGROUND);
CallHook(WUPS_LOADER_HOOK_APPLICATION_END);
CallHook(WUPS_LOADER_HOOK_DEINIT_PLUGIN); CallHook(WUPS_LOADER_HOOK_DEINIT_PLUGIN);
uint32_t old = gAppStatus;
gAppStatus = 3;
CallHook(WUPS_LOADER_HOOK_APP_STATUS_CHANGED);
gAppStatus = old;
CallHook(WUPS_LOADER_HOOK_ENDING_APPLICATION);
// Restore patches as the patched functions could change. // Restore patches as the patched functions could change.
RestorePatches(); RestorePatches();
DynamicLinkingHelper::getInstance()->clearAll(); DynamicLinkingHelper::getInstance()->clearAll();
gInBackground = false;
} }
@ -114,7 +113,6 @@ void ResolveRelocations() {
if(!DynamicLinkingHelper::getInstance()->fillRelocations(relocations)) { if(!DynamicLinkingHelper::getInstance()->fillRelocations(relocations)) {
OSFatal("fillRelocations failed."); OSFatal("fillRelocations failed.");
} }
} }
void afterLoadAndLink() { void afterLoadAndLink() {
@ -129,11 +127,25 @@ void afterLoadAndLink() {
} }
extern "C" void doStart(int argc, char **argv);
// We need to wrap it to make sure the main function is called AFTER our code.
// The compiler tries to optimize this otherwise and calling the main function earlier
extern "C" int _start(int argc, char **argv) { extern "C" int _start(int argc, char **argv) {
if(gAppStatus == 2) { doStart(argc,argv);
//"No, we don't want to patch stuff again."); return ( (int (*)(int, char **))(*(unsigned int*)0x1005E040) )(argc, argv);
return ( (int (*)(int, char **))(*(unsigned int*)0x1005E040) )(argc, argv); }
extern "C" void doStart(int argc, char **argv) {
coreinit_handle = 0;
InitOSFunctionPointers();
if(gInBackground) {
CallHook(WUPS_LOADER_HOOK_APPLET_START);
return;
} }
gInBackground = true;
coreinit_handle = 0; coreinit_handle = 0;
InitOSFunctionPointers(); InitOSFunctionPointers();
InitSocketFunctionPointers(); InitSocketFunctionPointers();
@ -149,11 +161,19 @@ extern "C" int _start(int argc, char **argv) {
memset(&tv_store,0,sizeof(tv_store)); memset(&tv_store,0,sizeof(tv_store));
memset(&drc_store,0,sizeof(drc_store)); memset(&drc_store,0,sizeof(drc_store));
log_init();
if(!MemoryMapping::isMemoryMapped()) { if(!MemoryMapping::isMemoryMapped()) {
MemoryMapping::setupMemoryMapping(); MemoryMapping::setupMemoryMapping();
// Switch to custom heap memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data));
DCFlushRange((void*)&gbl_replacement_data,sizeof(gbl_replacement_data));
ICInvalidateRange((void*)&gbl_replacement_data,sizeof(gbl_replacement_data));
memset((void*)&gbl_dyn_linking_data,0,sizeof(gbl_dyn_linking_data));
DCFlushRange((void*)&gbl_dyn_linking_data,sizeof(gbl_dyn_linking_data));
ICInvalidateRange((void*)&gbl_dyn_linking_data,sizeof(gbl_dyn_linking_data));
// Switch to custom heap
//Does not work =( //Does not work =(
//initMemory(); //initMemory();
//SplashScreen(1, "Memory mapping was completed!", 0,0); //SplashScreen(1, "Memory mapping was completed!", 0,0);
@ -168,20 +188,15 @@ extern "C" int _start(int argc, char **argv) {
DCFlushRange(ipcFunction,4); DCFlushRange(ipcFunction,4);
ICInvalidateRange(ipcFunction,4); ICInvalidateRange(ipcFunction,4);
log_init(); // Do patches so memory mapping works fine with some functions.
DEBUG_FUNCTION_LINE("log init done\n");
DEBUG_FUNCTION_LINE("Patch own stuff\n");
// Do patches so memmory mapping works fine with some functions.
PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static); PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static);
// mount sd card. // mount sd card.
mount_sd_fat("sd"); mount_sd_fat("sd");
PluginLoader * pluginLoader = new PluginLoader((void*)PLUGIN_LOCATION_START_ADDRESS, (void*)PLUGIN_LOCATION_END_ADDRESS); DEBUG_FUNCTION_LINE("Mounted SD\n");
PluginLoader * pluginLoader = new PluginLoader((void*)PLUGIN_LOCATION_START_ADDRESS, (void*)PLUGIN_LOCATION_END_ADDRESS);
std::vector<PluginInformation *> pluginList = pluginLoader->getPluginInformation("sd:/wiiu/autoboot_plugins/"); std::vector<PluginInformation *> pluginList = pluginLoader->getPluginInformation("sd:/wiiu/autoboot_plugins/");
pluginLoader->loadAndLinkPlugins(pluginList); pluginLoader->loadAndLinkPlugins(pluginList);
pluginLoader->clearPluginInformation(pluginList); pluginLoader->clearPluginInformation(pluginList);
@ -189,7 +204,6 @@ extern "C" int _start(int argc, char **argv) {
afterLoadAndLink(); afterLoadAndLink();
} else { } else {
log_init();
DEBUG_FUNCTION_LINE("Mapping was already done\n"); DEBUG_FUNCTION_LINE("Mapping was already done\n");
//unmount_sd_fat("sd"); //unmount_sd_fat("sd");
mount_sd_fat("sd"); mount_sd_fat("sd");
@ -200,15 +214,12 @@ extern "C" int _start(int argc, char **argv) {
//MemoryMapping::readTestValuesFromMemory(); //MemoryMapping::readTestValuesFromMemory();
} }
std::vector<dyn_linking_relocation_entry_t *> relocations = DynamicLinkingHelper::getInstance()->getAllValidDynamicLinkingRelocations(); ResolveRelocations();
DEBUG_FUNCTION_LINE("Found relocation information for %d functions\n",relocations.size());
if(!DynamicLinkingHelper::getInstance()->fillRelocations(relocations)) { MemoryUtils::init();
OSFatal("fillRelocations failed.");
}
DEBUG_FUNCTION_LINE("Apply patches.\n"); DEBUG_FUNCTION_LINE("Apply patches.\n");
ApplyPatchesAndCallHookStartingApp(); ApplyPatchesAndCallHookStartingApp();
DEBUG_FUNCTION_LINE("Patches applied. Running application.\n");
return ( (int (*)(int, char **))(*(unsigned int*)0x1005E040) )(argc, argv);
} }

View File

@ -1,37 +1,10 @@
#include <utils/logger.h> #include <utils/logger.h>
#include <utils/function_patcher.h> #include <utils/function_patcher.h>
#include "common/retain_vars.h"
#include "hooks_patcher.h" #include "hooks_patcher.h"
#include "utils/overlay_helper.h"
#include "utils/ConfigUtils.h"
#include "utils.h"
#include "fs/sd_fat_devoptab.h"
//#include <video/shaders/Texture2DShader.h>
DECL(uint32_t, ProcUIProcessMessages, uint32_t u) {
uint32_t res = real_ProcUIProcessMessages(u);
// Only continue if we are in the "right" application.
if(res != gAppStatus && OSGetTitleID() == gGameTitleID) {
DEBUG_FUNCTION_LINE("App status changed from %d to %d \n",gAppStatus,res);
gAppStatus = res;
CallHook(WUPS_LOADER_HOOK_APP_STATUS_CHANGED);
if(gAppStatus == WUPS_APP_STATUS_CLOSED) {
CallHook(WUPS_LOADER_HOOK_ENDING_APPLICATION);
ConfigUtils::saveConfigToSD();
unmount_sd_fat("sd");
//DeInit();
//Texture2DShader::destroyInstance();
}
}
return res;
}
hooks_magic_t method_hooks_hooks[] __attribute__((section(".data"))) = { hooks_magic_t method_hooks_hooks[] __attribute__((section(".data"))) = {
MAKE_MAGIC(ProcUIProcessMessages, LIB_PROC_UI, DYNAMIC_FUNCTION),
}; };
uint32_t method_hooks_size_hooks __attribute__((section(".data"))) = sizeof(method_hooks_hooks) / sizeof(hooks_magic_t); uint32_t method_hooks_size_hooks __attribute__((section(".data"))) = sizeof(method_hooks_hooks) / sizeof(hooks_magic_t);
//! buffer to store our instructions needed for our replacements //! buffer to store our instructions needed for our replacements

View File

@ -9,18 +9,10 @@
#include "memory/memory_mapping.h" #include "memory/memory_mapping.h"
#include "utils/mem_utils.h" #include "utils/mem_utils.h"
#include "dynamic_libs/vpad_functions.h" #include "dynamic_libs/vpad_functions.h"
#include "dynamic_libs/coreinit.h"
#include "fs/sd_fat_devoptab.h"
//#include "utils/texture_utils.h" //#include "utils/texture_utils.h"
DECL(void, __PPCExit, void) {
// Only continue if we are in the "right" application.
if(OSGetTitleID() == gGameTitleID) {
DEBUG_FUNCTION_LINE("__PPCExit\n");
//CallHook(WUPS_LOADER_HOOK_ENDING_APPLICATION);
}
real___PPCExit();
}
DECL_FUNCTION(uint32_t, __OSPhysicalToEffectiveCached, uint32_t phyiscalAddress) { DECL_FUNCTION(uint32_t, __OSPhysicalToEffectiveCached, uint32_t phyiscalAddress) {
uint32_t result = real___OSPhysicalToEffectiveCached(phyiscalAddress); uint32_t result = real___OSPhysicalToEffectiveCached(phyiscalAddress);
if(result == 0) { if(result == 0) {
@ -316,8 +308,43 @@ DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer* cbuf, int32_
return real_GX2CopyColorBufferToScanBuffer(&g_vid_main_cbuf,target); return real_GX2CopyColorBufferToScanBuffer(&g_vid_main_cbuf,target);
}*/ }*/
static uint32_t lastData0 = 0;
DECL(uint32_t, OSReceiveMessage, OSMessageQueue *queue, OSMessage *message, uint32_t flags) {
if(flags == 0x15154848) {
CallHook(WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND);
CallHook(WUPS_LOADER_HOOK_APPLICATION_END);
gInBackground = false;
DCFlushRange(&gInBackground,4);
return false;
}
int32_t res = real_OSReceiveMessage(queue, message, flags);
if(queue == OSGetSystemMessageQueue()) {
if(message != NULL) {
if(lastData0 != message->data0) {
if(message->data0 == 0xFACEF000) {
CallHook(WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND);
} else if(message->data0 == 0xD1E0D1E0) {
CallHook(WUPS_LOADER_HOOK_APPLICATION_END);
gInBackground = false;
DCFlushRange(&gInBackground,4);
unmount_sd_fat("sd");
}
}
lastData0 = message->data0;
}
}
return res;
}
DECL(void, OSReleaseForeground) {
if(OSGetCoreId() == 1) {
CallHook(WUPS_LOADER_HOOK_RELEASE_FOREGROUND);
}
real_OSReleaseForeground();
}
hooks_magic_t method_hooks_hooks_static[] __attribute__((section(".data"))) = { hooks_magic_t method_hooks_hooks_static[] __attribute__((section(".data"))) = {
MAKE_MAGIC(__PPCExit, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(GX2SetTVBuffer, LIB_GX2, STATIC_FUNCTION), MAKE_MAGIC(GX2SetTVBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2SetDRCBuffer, LIB_GX2, STATIC_FUNCTION), MAKE_MAGIC(GX2SetDRCBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2WaitForVsync, LIB_GX2, STATIC_FUNCTION), MAKE_MAGIC(GX2WaitForVsync, LIB_GX2, STATIC_FUNCTION),
@ -328,6 +355,8 @@ hooks_magic_t method_hooks_hooks_static[] __attribute__((section(".data"))) = {
MAKE_MAGIC(__OSPhysicalToEffectiveUncached, LIB_CORE_INIT, STATIC_FUNCTION), MAKE_MAGIC(__OSPhysicalToEffectiveUncached, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(__OSPhysicalToEffectiveCached, LIB_CORE_INIT, STATIC_FUNCTION), MAKE_MAGIC(__OSPhysicalToEffectiveCached, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(OSEffectiveToPhysical, LIB_CORE_INIT, STATIC_FUNCTION), MAKE_MAGIC(OSEffectiveToPhysical, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(OSReceiveMessage, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(OSReleaseForeground, LIB_CORE_INIT, STATIC_FUNCTION)
}; };
uint32_t method_hooks_size_hooks_static __attribute__((section(".data"))) = sizeof(method_hooks_hooks_static) / sizeof(hooks_magic_t); uint32_t method_hooks_size_hooks_static __attribute__((section(".data"))) = sizeof(method_hooks_hooks_static) / sizeof(hooks_magic_t);

View File

@ -381,7 +381,7 @@ bool PluginInformation::metadataRead(Elf *elf, Elf32_Sym *symtab, size_t symtab_
description = ""; description = "";
} }
if (wups == NULL || strcmp(wups, "0.1") != 0) { if (wups == NULL || strcmp(wups, "0.2") != 0) {
DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Unrecognised WUPS version.\n", path); DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Unrecognised WUPS version.\n", path);
goto exit_error; goto exit_error;
} }

View File

@ -35,6 +35,26 @@ bool HasHookCallHook(wups_loader_hook_type_t hook_type) {
return false; return false;
} }
static const char** hook_names = (const char *[]){
"WUPS_LOADER_HOOK_INIT_FS",
"WUPS_LOADER_HOOK_INIT_OVERLAY",
"WUPS_LOADER_HOOK_INIT_KERNEL",
"WUPS_LOADER_HOOK_INIT_VID_MEM",
"WUPS_LOADER_HOOK_INIT_PLUGIN",
"WUPS_LOADER_HOOK_DEINIT_PLUGIN",
"WUPS_LOADER_HOOK_APPLICATION_START",
"WUPS_LOADER_HOOK_FUNCTIONS_PATCHED",
"WUPS_LOADER_HOOK_RELEASE_FOREGROUND",
"WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND",
"WUPS_LOADER_HOOK_APPLICATION_END",
"WUPS_LOADER_HOOK_CONFIRM_RELEASE_FOREGROUND",
"WUPS_LOADER_HOOK_SAVES_DONE_READY_TO_RELEASE",
"WUPS_LOADER_HOOK_VSYNC",
"WUPS_LOADER_HOOK_GET_CONFIG",
"WUPS_LOADER_HOOK_VID_DRC_DRAW",
"WUPS_LOADER_HOOK_VID_TV_DRAW",
"WUPS_LOADER_HOOK_APPLET_START"};
void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed) { void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed) {
for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) { for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) {
replacement_data_plugin_t * plugin_data = &gbl_replacement_data.plugin_data[plugin_index]; replacement_data_plugin_t * plugin_data = &gbl_replacement_data.plugin_data[plugin_index];
@ -42,13 +62,12 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed)
continue; continue;
} }
#warning TODO: change the order of the wups_loader_hook_type_t enum before an offical release.
//DEBUG_FUNCTION_LINE("Checking hook functions for %s.\n",plugin_data->plugin_name); //DEBUG_FUNCTION_LINE("Checking hook functions for %s.\n",plugin_data->plugin_name);
//DEBUG_FUNCTION_LINE("Found hooks: %d\n",plugin_data->number_used_hooks); //DEBUG_FUNCTION_LINE("Found hooks: %d\n",plugin_data->number_used_hooks);
for(int32_t j=0; j<plugin_data->number_used_hooks; j++) { for(int32_t j=0; j<plugin_data->number_used_hooks; j++) {
replacement_data_hook_t * hook_data = &plugin_data->hooks[j]; replacement_data_hook_t * hook_data = &plugin_data->hooks[j];
if(hook_data->type == hook_type) { if(hook_data->type == hook_type) {
//DEBUG_FUNCTION_LINE("Calling hook of type %d for plugin %s\n",hook_data->type,plugin_data->plugin_name); DEBUG_FUNCTION_LINE("Calling hook of type %s for plugin %s\n",hook_names[hook_data->type],plugin_data->plugin_name);
void * func_ptr = hook_data->func_pointer; void * func_ptr = hook_data->func_pointer;
//TODO: Switch cases depending on arguments etc. //TODO: Switch cases depending on arguments etc.
// Adding arguments! // Adding arguments!
@ -79,7 +98,7 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed)
((void (*)(void))((uint32_t*)func_ptr) )(); ((void (*)(void))((uint32_t*)func_ptr) )();
} else if(hook_type == WUPS_LOADER_HOOK_DEINIT_PLUGIN) { } else if(hook_type == WUPS_LOADER_HOOK_DEINIT_PLUGIN) {
((void (*)(void))((uint32_t*)func_ptr) )(); ((void (*)(void))((uint32_t*)func_ptr) )();
} else if(hook_type == WUPS_LOADER_HOOK_STARTING_APPLICATION) { } else if(hook_type == WUPS_LOADER_HOOK_APPLICATION_START) {
wups_loader_app_started_args_t args; wups_loader_app_started_args_t args;
memset(&args,0,sizeof(args)); memset(&args,0,sizeof(args));
///*if(gSDInitDone & WUPS_SD_MOUNTED) { ///*if(gSDInitDone & WUPS_SD_MOUNTED) {
@ -94,22 +113,16 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed)
((void (*)(wups_loader_app_started_args_t))((uint32_t*)func_ptr) )(args); ((void (*)(wups_loader_app_started_args_t))((uint32_t*)func_ptr) )(args);
} else if(hook_type == WUPS_LOADER_HOOK_FUNCTIONS_PATCHED) { } else if(hook_type == WUPS_LOADER_HOOK_FUNCTIONS_PATCHED) {
((void (*)(void))((uint32_t*)func_ptr))(); ((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_ENDING_APPLICATION) { } else if(hook_type == WUPS_LOADER_HOOK_APPLICATION_END) {
((void (*)(void))((uint32_t*)func_ptr))(); ((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_VSYNC) { } else if(hook_type == WUPS_LOADER_HOOK_VSYNC) {
((void (*)(void))((uint32_t*)func_ptr))(); ((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_APP_STATUS_CHANGED) { } else if(hook_type == WUPS_LOADER_HOOK_RELEASE_FOREGROUND) {
wups_loader_app_status_t status; ((void (*)(void))((uint32_t*)func_ptr))();
if(gAppStatus == 0) { } else if(hook_type == WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND) {
status = WUPS_APP_STATUS_FOREGROUND; ((void (*)(void))((uint32_t*)func_ptr))();
} else if(gAppStatus == 2) { } else if(hook_type == WUPS_LOADER_HOOK_APPLET_START) {
status = WUPS_APP_STATUS_BACKGROUND; ((void (*)(void))((uint32_t*)func_ptr))();
} else if(gAppStatus == 3) {
status = WUPS_APP_STATUS_CLOSED;
} else {
status = WUPS_APP_STATUS_UNKNOWN;
}
((void (*)(wups_loader_app_status_t))((uint32_t*)func_ptr))(status);
} else if(hook_type == WUPS_LOADER_HOOK_INIT_KERNEL) { } else if(hook_type == WUPS_LOADER_HOOK_INIT_KERNEL) {
// Only call the hook if kernel is allowed. // Only call the hook if kernel is allowed.
if(plugin_data->kernel_allowed) { if(plugin_data->kernel_allowed) {