From a5b1f1d2eb38524a0b92b1a290a18f5760156522 Mon Sep 17 00:00:00 2001 From: illusion0001 <37698908+illusion0001@users.noreply.github.com> Date: Fri, 23 Jun 2023 00:54:34 -0500 Subject: [PATCH] Rename `module_start` to `plugin_load` --- plugin_src/afr/source/main.c | 14 +++- plugin_src/aio_fix_505/source/main.c | 14 +++- plugin_src/button_swap/source/main.c | 14 +++- plugin_src/fliprate_remover/source/main.c | 14 +++- plugin_src/force_1080p_display/source/main.c | 14 +++- plugin_src/force_30_fps/source/main.c | 14 +++- plugin_src/game_call_example/source/main.c | 14 +++- plugin_src/game_patch/source/main.cpp | 21 ++++-- plugin_src/game_patch/source/patch.cpp | 6 +- plugin_src/gamepad_helper/source/main.c | 14 +++- plugin_src/no_share_watermark/source/main.c | 14 +++- plugin_src/plugin_loader/source/main.c | 79 ++++++++++++++------ plugin_src/plugin_template/source/main.c | 18 ++++- 13 files changed, 197 insertions(+), 53 deletions(-) diff --git a/plugin_src/afr/source/main.c b/plugin_src/afr/source/main.c index e46e2ca5..faac2d54 100644 --- a/plugin_src/afr/source/main.c +++ b/plugin_src/afr/source/main.c @@ -102,7 +102,7 @@ s32 sceKernelOpen_hook(const char *path, s32 flags, OrbisKernelMode mode) return fd; } -s32 attr_module_hidden module_start(s64 argc, const void *args) +s32 attr_public plugin_load(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); @@ -118,7 +118,7 @@ s32 attr_module_hidden module_start(s64 argc, const void *args) return 0; } -s32 attr_module_hidden module_stop(s64 argc, const void *args) +s32 attr_public plugin_unload(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); UNHOOK(sceKernelOpen); @@ -126,3 +126,13 @@ s32 attr_module_hidden module_stop(s64 argc, const void *args) UNHOOK(fopen); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} diff --git a/plugin_src/aio_fix_505/source/main.c b/plugin_src/aio_fix_505/source/main.c index 1fa504b1..51ea7b88 100644 --- a/plugin_src/aio_fix_505/source/main.c +++ b/plugin_src/aio_fix_505/source/main.c @@ -307,7 +307,7 @@ s32 sceKernelAioSubmitWriteCommandsMultiple_hook(SceKernelAioRWRequest req[], s3 return 0; } -s32 attr_module_hidden module_start(s64 argc, const void* args) { +s32 attr_public plugin_load(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); boot_ver(); @@ -353,7 +353,7 @@ s32 attr_module_hidden module_start(s64 argc, const void* args) { return 0; } -s32 attr_module_hidden module_stop(s64 argc, const void* args) { +s32 attr_public plugin_unload(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); UNHOOK(sceKernelAioInitializeImpl); UNHOOK(sceKernelAioDeleteRequest); @@ -370,3 +370,13 @@ s32 attr_module_hidden module_stop(s64 argc, const void* args) { UNHOOK(sceKernelAioSubmitWriteCommandsMultiple); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} diff --git a/plugin_src/button_swap/source/main.c b/plugin_src/button_swap/source/main.c index 356518aa..e8c1cfe0 100644 --- a/plugin_src/button_swap/source/main.c +++ b/plugin_src/button_swap/source/main.c @@ -23,7 +23,7 @@ s32 sceSystemServiceParamGetInt_hook(s32 paramId, s32 *value) { return ret; } -s32 attr_module_hidden module_start(s64 argc, const void *args) { +s32 attr_public plugin_load(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); boot_ver(); @@ -34,8 +34,18 @@ s32 attr_module_hidden module_start(s64 argc, const void *args) { return 0; } -s32 attr_module_hidden module_stop(s64 argc, const void *args) { +s32 attr_public plugin_unload(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); UNHOOK(sceSystemServiceParamGetInt); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} diff --git a/plugin_src/fliprate_remover/source/main.c b/plugin_src/fliprate_remover/source/main.c index b9acab05..5883662e 100644 --- a/plugin_src/fliprate_remover/source/main.c +++ b/plugin_src/fliprate_remover/source/main.c @@ -20,7 +20,7 @@ s32 sceVideoOutSetFlipRate_hook(s32 handle, s32 fliprate){ return 0; } -s32 attr_module_hidden module_start(s64 argc, const void *args) { +s32 attr_public plugin_load(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); boot_ver(); @@ -28,8 +28,18 @@ s32 attr_module_hidden module_start(s64 argc, const void *args) { return 0; } -s32 attr_module_hidden module_stop(s64 argc, const void *args) { +s32 attr_public plugin_unload(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); UNHOOK(sceVideoOutSetFlipRate); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} diff --git a/plugin_src/force_1080p_display/source/main.c b/plugin_src/force_1080p_display/source/main.c index da0293ff..da13b477 100644 --- a/plugin_src/force_1080p_display/source/main.c +++ b/plugin_src/force_1080p_display/source/main.c @@ -45,7 +45,7 @@ s32 sceVideoOutGetResolutionStatus_hook(int handle, OrbisVideoOutResolutionStatu return ret; } -s32 attr_module_hidden module_start(s64 argc, const void *args) { +s32 attr_public plugin_load(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); boot_ver(); @@ -53,8 +53,18 @@ s32 attr_module_hidden module_start(s64 argc, const void *args) { return 0; } -s32 attr_module_hidden module_stop(s64 argc, const void *args) { +s32 attr_public plugin_unload(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); UNHOOK(sceVideoOutGetResolutionStatus); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} diff --git a/plugin_src/force_30_fps/source/main.c b/plugin_src/force_30_fps/source/main.c index 9c52bd6b..0a0c142d 100644 --- a/plugin_src/force_30_fps/source/main.c +++ b/plugin_src/force_30_fps/source/main.c @@ -20,7 +20,7 @@ s32 sceVideoOutSetFlipRate_hook(s32 handle, s32 fliprate) handle, 1); } -s32 attr_module_hidden module_start(s64 argc, const void *args) +s32 attr_public plugin_load(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); @@ -29,9 +29,19 @@ s32 attr_module_hidden module_start(s64 argc, const void *args) return 0; } -s32 attr_module_hidden module_stop(s64 argc, const void *args) +s32 attr_public plugin_unload(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); UNHOOK(sceVideoOutSetFlipRate); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} diff --git a/plugin_src/game_call_example/source/main.c b/plugin_src/game_call_example/source/main.c index 87f81b81..c1f96706 100644 --- a/plugin_src/game_call_example/source/main.c +++ b/plugin_src/game_call_example/source/main.c @@ -39,7 +39,7 @@ void* my_thread(void* args) return NULL; } -int32_t attr_module_hidden module_start(size_t argc, const void *args) +int32_t attr_public plugin_load(int32_t argc, const char* argv[]) { if (sys_sdk_proc_info(&procInfo) == 0) { @@ -58,9 +58,19 @@ int32_t attr_module_hidden module_start(size_t argc, const void *args) return 0; } -int32_t attr_module_hidden module_stop(size_t argc, const void *args) +int32_t attr_public plugin_unload(int32_t argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] %s Plugin Ended.\n", g_pluginName); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} diff --git a/plugin_src/game_patch/source/main.cpp b/plugin_src/game_patch/source/main.cpp index f60b2cb5..6d85a94d 100644 --- a/plugin_src/game_patch/source/main.cpp +++ b/plugin_src/game_patch/source/main.cpp @@ -55,7 +55,8 @@ void get_key_init(void) if (res) { - final_printf("file %s not found\nerror: 0x%08x", input_file, res); + final_printf("file %s not found\n", input_file); + final_printf("error: 0x%08x\n", res); return; } @@ -86,7 +87,7 @@ void get_key_init(void) debug_printf("AppElf: \"%s\"\n", AppElfData); u64 hashout = patch_hash_calc(TitleData, NameData, AppVerData, input_file, AppElfData); - char settings_path[MAX_PATH_]; + char settings_path[MAX_PATH_] = {0}; snprintf(settings_path, sizeof(settings_path), BASE_PATH_PATCH_SETTINGS "/0x%016lx.txt", hashout); final_printf("Settings path: %s\n", settings_path); s32 res = Read_File(settings_path, &buffer2, &size2, 0); @@ -239,7 +240,7 @@ void make_folders(void) } extern "C" { -s32 attr_module_hidden module_start(s64 argc, const void *args) { +s32 attr_public plugin_load(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); boot_ver(); @@ -265,11 +266,19 @@ s32 attr_module_hidden module_start(s64 argc, const void *args) { NotifyStatic(TEX_ICON_SYSTEM, "Unable to get process info from sys_sdk_proc_info"); return -1; } -} -extern "C" { -s32 attr_module_hidden module_stop(s64 argc, const void *args) { +s32 attr_public plugin_unload(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} } diff --git a/plugin_src/game_patch/source/patch.cpp b/plugin_src/game_patch/source/patch.cpp index 6fcb9864..b87548ae 100644 --- a/plugin_src/game_patch/source/patch.cpp +++ b/plugin_src/game_patch/source/patch.cpp @@ -25,7 +25,7 @@ char* unescape(const char *s) { break; case 'x': { - char hex_string[3]; + char hex_string[3] = {0}; u32 val = 0; hex_string[0] = s[++i]; hex_string[1] = s[++i]; @@ -134,7 +134,7 @@ constexpr u64 djb2_hash(const char *str) { u64 patch_hash_calc(const char *title, const char *name, const char *app_ver, const char *title_id, const char *elf) { u64 output_hash = 0; - char hash_str[256]; + char hash_str[256] = {0}; snprintf(hash_str, sizeof(hash_str), "%s%s%s%s%s", title, name, app_ver, title_id, elf); output_hash = djb2_hash(hash_str); @@ -273,7 +273,7 @@ void patch_data1(const char* patch_type_str, u64 addr, const char *value, uint32 sys_proc_rw(addr + i, nop_byte, sizeof(nop_byte)); } u8 jump_32[] = { 0xe9, 0x00, 0x00, 0x00, 0x00 }; - s32 target_jmp = (s32) (jump_target - addr - 5); + s32 target_jmp = (s32) (jump_target - addr - sizeof(jump_32)); s32 target_return = (s32) (addr) - (code_cave_end); sys_proc_rw(jump_target, bytearray, bytearray_size); sys_proc_rw(addr, jump_32, sizeof(jump_32)); diff --git a/plugin_src/gamepad_helper/source/main.c b/plugin_src/gamepad_helper/source/main.c index 1c95d792..7c5a1b5d 100644 --- a/plugin_src/gamepad_helper/source/main.c +++ b/plugin_src/gamepad_helper/source/main.c @@ -209,7 +209,7 @@ int32_t load_config(ini_table_s* table, const char* section_name) { return 0; } -s32 attr_module_hidden module_start(s64 argc, const void* args) { +s32 attr_public plugin_load(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); boot_ver(); @@ -333,7 +333,7 @@ s32 attr_module_hidden module_start(s64 argc, const void* args) { return 0; } -s32 attr_module_hidden module_stop(s64 argc, const void* args) { +s32 attr_public plugin_unload(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); UNHOOK(scePadRead); UNHOOK(scePadReadState); @@ -350,3 +350,13 @@ s32 attr_module_hidden module_stop(s64 argc, const void* args) { return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} diff --git a/plugin_src/no_share_watermark/source/main.c b/plugin_src/no_share_watermark/source/main.c index d9f5297b..a6fa2c34 100644 --- a/plugin_src/no_share_watermark/source/main.c +++ b/plugin_src/no_share_watermark/source/main.c @@ -62,7 +62,7 @@ s32 sceScreenShotDisable_hook(void){ return 0; } -s32 attr_module_hidden module_start(s64 argc, const void *args) { +s32 attr_public plugin_load(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); boot_ver(); @@ -78,7 +78,7 @@ s32 attr_module_hidden module_start(s64 argc, const void *args) { return 0; } -s32 attr_module_hidden module_stop(s64 argc, const void *args) { +s32 attr_public plugin_unload(s32 argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); UNHOOK(sceScreenShotSetOverlayImage); UNHOOK(sceScreenShotSetOverlayImageWithOrigin); @@ -88,3 +88,13 @@ s32 attr_module_hidden module_stop(s64 argc, const void *args) { UNHOOK(sceRemoteplayProhibitStreaming); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +} diff --git a/plugin_src/plugin_loader/source/main.c b/plugin_src/plugin_loader/source/main.c index a19a3460..3d0917dd 100644 --- a/plugin_src/plugin_loader/source/main.c +++ b/plugin_src/plugin_loader/source/main.c @@ -37,21 +37,22 @@ bool file_exists(const char* filename) void create_template_config(void) { final_printf("Creating new %s file\n", PLUGIN_CONFIG_PATH); - const char *file_str = "" - "[" PLUGIN_SETTINGS_SECTION "]\n" - "; Global settings for plugin loader.\n" - "; Affects every app/process boot.\n" - "show_load_notification=true\n" - "; Details for show_load_notification\n" - "; Shows how many plugins were successfully loaded.\n" - "; Valid options: false or true.\n" - "\n" - "; Load plugins in default section regardless of Title ID\n" - "[default]\n" - ";/data/GoldHEN/plugins/example.prx\n" - ";/data/GoldHEN/plugins/example2.prx\n" - "\n" - "; Note: text following the ; are comments\n"; + // compile time + #define DEFAULT_INI_DATA "" \ + "[" PLUGIN_SETTINGS_SECTION "]\n" \ + "; Global settings for plugin loader.\n" \ + "; Affects every app/process boot.\n" \ + "show_load_notification=true\n" \ + "; Details for show_load_notification\n" \ + "; Shows how many plugins were successfully loaded.\n" \ + "; Valid options: false or true.\n" \ + "\n" \ + "; Load plugins in default section regardless of Title ID\n" \ + "[default]\n" \ + ";/data/GoldHEN/plugins/example.prx\n" \ + ";/data/GoldHEN/plugins/example2.prx\n" \ + "\n" \ + "; Note: text following the ; are comments\n" // Does not work, may not have write access. //FILE* f = fopen(PLUGIN_CONFIG_PATH, "w"); @@ -63,11 +64,11 @@ void create_template_config(void) int32_t f = sceKernelOpen(PLUGIN_CONFIG_PATH, 0x200 | 0x001, 0777); if (f < 0) { - final_printf("Failed to create file \"%s\"\n", PLUGIN_CONFIG_PATH); + final_printf("Failed to create file \"%s\" 0x%08x\n", PLUGIN_CONFIG_PATH, f); return; } - sceKernelWrite(f, file_str, strlen(file_str)); + sceKernelWrite(f, DEFAULT_INI_DATA, strlen(DEFAULT_INI_DATA)); sceKernelClose(f); } @@ -134,7 +135,7 @@ void load_plugins(ini_section_s *section, uint32_t *load_count) } if (entry->key[0] != '/') { - char notify_msg[160]; + char notify_msg[160] = {0}; snprintf(notify_msg, sizeof(notify_msg), "Path:\n\"%s\"\nis wrong!\nPlugin will not load.", entry->key); if (!notifi_shown) { @@ -159,13 +160,45 @@ void load_plugins(ini_section_s *section, uint32_t *load_count) final_printf("Error loading Plugin %s! Error code 0x%08x (%i)\n", entry->key, result, result); } else { - char plugin_entry[128]; + int32_t ret = 0; + bool load_success = false; const char** ModuleName = NULL; - int ret = sceKernelDlsym(result, "g_pluginName", (void**)&ModuleName); + // TODO: accept user provided arguments + int32_t(*plugin_load_ret)(void) = NULL; + int32_t(*plugin_unload_ret)(void) = NULL; + ret = sceKernelDlsym(result, "g_pluginName", (void**)&ModuleName); final_printf("Loaded Plugin %s\n", entry->key); final_printf("Plugin Handle 0x%08x Dlsym 0x%08x\n", result, ret); - *load_count += 1; - if (ModuleName) + ret = sceKernelDlsym(result, "plugin_load", (void**)&plugin_load_ret); + final_printf("plugin_load Dlsym 0x%08x @ 0x%p\n", ret, plugin_load_ret); + ret = sceKernelDlsym(result, "plugin_unload", (void**)&plugin_unload_ret); + final_printf("plugin_unload Dlsym 0x%08x @ 0x%p\n", ret, plugin_unload_ret); + if (plugin_load_ret && plugin_unload_ret) + { + final_printf("Starting plugin...\n"); + int32_t prx_ret = plugin_load_ret(); + final_printf("plugin_load returned with 0x%08x\n", prx_ret); + if (prx_ret || prx_ret < 0) + { + final_printf("Program returned non zero, Starting plugin_unload...\n"); + int32_t prx_ret = plugin_unload_ret(); + final_printf("plugin_unload returned with 0x%08x\n", prx_ret); + } + else if (prx_ret == 0) + { + final_printf("plugin_load exit successful 0x%08x\n", prx_ret); + *load_count += 1; + load_success = true; + } + } + else + { + final_printf("Unable to find plugin_load or plugin_unload!\n"); + load_success = false; + continue; + } + char plugin_entry[128] = {0}; + if (ModuleName && load_success) { snprintf(plugin_entry, sizeof(plugin_entry), "%u. %s\n", *load_count, *ModuleName); } @@ -289,7 +322,7 @@ int32_t attr_module_hidden module_start(size_t argc, const void *args) { if (load_count > 0) { - char notify_msg[128]; + char notify_msg[128] = {0}; // trim newline size_t PluginLen = strlen(g_PluginDetails) - 1; if (g_PluginDetails[PluginLen] == '\n') diff --git a/plugin_src/plugin_template/source/main.c b/plugin_src/plugin_template/source/main.c index d9c12de6..e11608c8 100644 --- a/plugin_src/plugin_template/source/main.c +++ b/plugin_src/plugin_template/source/main.c @@ -9,16 +9,28 @@ attr_public const char *g_pluginDesc = "Example Plugin"; attr_public const char *g_pluginAuth = "(null)"; attr_public uint32_t g_pluginVersion = 0x00000100; // 1.00 -int32_t attr_module_hidden module_start(size_t argc, const void *args) { +int32_t attr_public plugin_load(int32_t argc, const char* argv[]) { final_printf("[GoldHEN] %s Plugin Started.\n", g_pluginName); final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] Plugin Author(s): %s\n", g_pluginAuth); - Notify(TEX_ICON_SYSTEM, "Hello from %s", g_pluginName); + char msg[128] = {0}; + snprintf(msg, sizeof(msg), "Hello from %s", g_pluginName); + NotifyStatic(TEX_ICON_SYSTEM, msg); return 0; } -int32_t attr_module_hidden module_stop(size_t argc, const void *args) { +int32_t attr_public plugin_unload(int32_t argc, const char* argv[]) { final_printf("[GoldHEN] <%s\\Ver.0x%08x> %s\n", g_pluginName, g_pluginVersion, __func__); final_printf("[GoldHEN] %s Plugin Ended.\n", g_pluginName); return 0; } + +s32 attr_module_hidden module_start(s64 argc, const void *args) +{ + return 0; +} + +s32 attr_module_hidden module_stop(s64 argc, const void *args) +{ + return 0; +}