From 72074d99049791a79b1f3ea4accf700ecf3135dc Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Fri, 23 Jun 2017 12:51:04 -0400 Subject: [PATCH 01/14] Force default DRC mode upon Inkstrike activation --- src/main.c | 8 +-- src/patcher/function_hooks.c | 100 +++++++++++++++++------------------ src/retain_vars.c | 4 +- src/retain_vars.h | 2 + 4 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/main.c b/src/main.c index 6a5fe86..6500ada 100644 --- a/src/main.c +++ b/src/main.c @@ -110,7 +110,7 @@ int Menu_Main() // Render IP selector and check for buttons u_serv_ip ip; - ip.full = ( (192<<24) | (168<<16) | (2<<8) | (15<<0) ); + ip.full = ( (192<<24) | (168<<16) | (86<<8) | (186<<0) ); VPADData vpad_data; s32 error; int delay = 0; @@ -186,7 +186,7 @@ int Menu_Main() { sel_ip++; sel_ip = sel_ip % 4; - delay = 12; + delay = 6; } } else if ((vpad_data.btns_h & VPAD_BUTTON_UP) && gui_mode == 0) @@ -194,7 +194,7 @@ int Menu_Main() if (--delay <= 0) { ip.digit[sel_ip]++; - delay = 12; + delay = 6; } } else if ((vpad_data.btns_h & VPAD_BUTTON_DOWN) && gui_mode == 0) @@ -202,7 +202,7 @@ int Menu_Main() if (--delay <= 0) { ip.digit[sel_ip]--; - delay = 12; + delay = 6; } } else diff --git a/src/patcher/function_hooks.c b/src/patcher/function_hooks.c index 2f4a8b9..b5d6451 100644 --- a/src/patcher/function_hooks.c +++ b/src/patcher/function_hooks.c @@ -194,7 +194,13 @@ DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan // 0x0 = normal // 0x1 = swap - if (drcMode == 1) + // the 1st if statement can also FORCE the drcMode to default when inkstrike is activated + + if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) + { + real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); + } + else { if (scan_target == 0x1) { @@ -205,10 +211,6 @@ DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan real_GX2CopyColorBufferToScanBuffer(colorBuffer, 0x1); } } - else - { - real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); - } } DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) @@ -238,69 +240,63 @@ DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) drcMode = !drcMode; } } - else - { - // switch on L and SELECT - if (buffer->btns_d & VPAD_BUTTON_MINUS) - { - drcMode = !drcMode; - } - } - } - else - { - // switch on L and SELECT - if (buffer->btns_d & VPAD_BUTTON_MINUS) - { - drcMode = !drcMode; - } + + // Checks special equipped pointer + if (*(inkstrikeEq - 0xC) != 0x3F800000) + { + uint32_t firstBase = *(uint32_t*)0x106E46E8; + if (firstBase > 0x1D000000 && firstBase < 0x27000000) + { + inkstrikeEq = (uint32_t*)(firstBase + 0x80); + spTimer = (uint32_t*)(firstBase + 0x80C); + } + } } + // switch on L and SELECT + if (buffer->btns_d & VPAD_BUTTON_MINUS && buffer->btns_h & VPAD_BUTTON_L) + { + drcMode = !drcMode; + } + // disable touchscreen input if the TV is on the DRC - if (drcMode == 1) + if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) {} + else { buffer->tpdata.touched = 0; buffer->tpdata1.touched = 0; buffer->tpdata2.touched = 0; } - + return ret; } DECL(void, VPADGetTPCalibratedPoint, int chan, VPADTPData *screen, VPADTPData *raw) { real_VPADGetTPCalibratedPoint(chan, screen, raw); - - // check for Splatoon - if (isSplatoon) - { - if (screenPressTimeout != 0) - { - screenPressTimeout--; - } - - // disable touchscreen input if the TV is on the DRC - if (drcMode == 1 && screenPressTimeout == 0) - { - screen->touched = 0; - raw->touched = 0; - } - else - { - // Swap once a touchscreen input is received during a match - if (screen->touched == 1 && gamemode != 0 && *gamemode != 0xFFFFFFFF) - { - drcMode = !drcMode; - screenPressTimeout = 300; - } - } - } + + // disable touchscreen input if the TV is on the DRC + if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) {} + else + { + screen->touched = 0; + raw->touched = 0; + } } DECL(void, VPADGetTPCalibratedPointEx, int chan, int resolution, VPADTPData *screen, VPADTPData *raw) { real_VPADGetTPCalibratedPointEx(chan, resolution, screen, raw); - + + // disable touchscreen input if the TV is on the DRC + if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) {} + else + { + screen->touched = 0; + raw->touched = 0; + } + + /* // check for Splatoon if (isSplatoon) { @@ -324,7 +320,7 @@ DECL(void, VPADGetTPCalibratedPointEx, int chan, int resolution, VPADTPData *scr screenPressTimeout = 300; } } - } + }*/ } /* ***************************************************************************** @@ -360,8 +356,8 @@ static struct hooks_magic_t { MAKE_MAGIC(FSIsEof, LIB_FS, STATIC_FUNCTION), MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION), MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION), - MAKE_MAGIC(VPADGetTPCalibratedPoint, LIB_VPAD, STATIC_FUNCTION), - MAKE_MAGIC(VPADGetTPCalibratedPointEx, LIB_VPAD, STATIC_FUNCTION) + MAKE_MAGIC(VPADGetTPCalibratedPoint, LIB_VPAD, STATIC_FUNCTION)//, + //MAKE_MAGIC(VPADGetTPCalibratedPointEx, LIB_VPAD, STATIC_FUNCTION) }; diff --git a/src/retain_vars.c b/src/retain_vars.c index 4b76f1a..1aa2fab 100644 --- a/src/retain_vars.c +++ b/src/retain_vars.c @@ -3,4 +3,6 @@ int isSplatoon __attribute__((section(".data"))) = 0; int drcMode __attribute__((section(".data"))) = 0; int screenPressTimeout __attribute__((section(".data"))) = 0; -uint32_t* gamemode __attribute__((section(".data"))) = (uint32_t*)0; \ No newline at end of file +uint32_t* gamemode __attribute__((section(".data"))) = (uint32_t*)0; +uint32_t* inkstrikeEq __attribute__((section(".data"))) = (uint32_t*)0x10000000; +uint32_t* spTimer __attribute__((section(".data"))) = (uint32_t*)0x10000000; \ No newline at end of file diff --git a/src/retain_vars.h b/src/retain_vars.h index 4c22123..a76a746 100644 --- a/src/retain_vars.h +++ b/src/retain_vars.h @@ -7,5 +7,7 @@ extern int isSplatoon; extern int drcMode; extern int screenPressTimeout; extern uint32_t* gamemode; +extern uint32_t* inkstrikeEq; +extern uint32_t* spTimer; #endif // _RETAIN_VARS_H_ \ No newline at end of file From 4aec16d89c84492cf1b48a35df5bf6e2b60c86cf Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Fri, 23 Jun 2017 13:00:00 -0400 Subject: [PATCH 02/14] Big menu changes in main.c and updated hooks --- src/main.c | 207 +++++++++++++++++++++++++---------- src/patcher/function_hooks.c | 19 ++-- src/retain_vars.c | 1 + src/retain_vars.h | 1 + 4 files changed, 160 insertions(+), 68 deletions(-) diff --git a/src/main.c b/src/main.c index 6500ada..2caa858 100644 --- a/src/main.c +++ b/src/main.c @@ -11,6 +11,7 @@ #include "dynamic_libs/fs_functions.h" #include "dynamic_libs/vpad_functions.h" #include "utils/logger.h" +#include "system/memory.h" #include "common/common.h" #include "patcher/function_hooks.h" #include "kernel/kernel_functions.h" @@ -19,7 +20,9 @@ #include "retain_vars.h" #define PRINT_TEXT1(x, y, str) { OSScreenPutFontEx(1, x, y, str); } -#define PRINT_TEXT2(x, y, _fmt, ...) { __os_snprintf(msg, 80, _fmt, __VA_ARGS__); OSScreenPutFontEx(1, x, y, msg); } +#define PRINT_TEXT2(x, y, ...) { snprintf(msg, 80, __VA_ARGS__); OSScreenPutFontEx(0, x, y, msg); OSScreenPutFontEx(1, x, y, msg); } +#define PRINT_TEXT3(x, y, _fmt, ...) { __os_snprintf(msg, 80, _fmt, __VA_ARGS__); OSScreenPutFontEx(1, x, y, msg); } + /* IP union */ typedef union u_serv_ip @@ -28,7 +31,7 @@ typedef union u_serv_ip uint32_t full; } u_serv_ip; -static unsigned int patched = 0; +//static unsigned int patched = 0; /* Entry point */ int Menu_Main() @@ -62,100 +65,146 @@ int Menu_Main() "li 4, 0\n" "bl memset\n" ); - - PatchMethodHooks(); - + if (strcasecmp("men.rpx", cosAppXmlInfoStruct.rpx_name) == 0) { log_printf("Wii U menu started, exiting.\n"); - + log_deinit(); return EXIT_RELAUNCH_ON_LOAD; } - + /* if (strlen(cosAppXmlInfoStruct.rpx_name) == 0) { log_printf("Returning to the Wii U menu.\n"); - + SYSLaunchMenu(); - + log_deinit(); return EXIT_RELAUNCH_ON_LOAD; - } + }*/ // Check for Splatoon (Gambit) - if (strcasecmp("Gambit.rpx", cosAppXmlInfoStruct.rpx_name) == 0) - { - log_printf("Splatoon enhanced swapping enabled.\n"); - isSplatoon = 1; - } - + if (strcasecmp("Gambit.rpx", cosAppXmlInfoStruct.rpx_name) == 0) + { + log_printf("Splatoon enhanced swapping enabled.\n"); + isSplatoon = 1; + } + log_printf("Starting the TCPGecko server.\n"); start_pygecko(); - - if (!patched) + + if (patched == 0) { - // Prepare screen - int screen_buf0_size = 0; - char msg[80]; - + memoryInitialize(); + + VPADInit(); + // Init screen and screen buffers OSScreenInit(); - screen_buf0_size = OSScreenGetBufferSizeEx(0); - OSScreenSetBufferEx(0, (void *)0xF4000000); - OSScreenSetBufferEx(1, (void *)0xF4000000 + screen_buf0_size); - + int screen_buf0_size = OSScreenGetBufferSizeEx(0); + int screen_buf1_size = OSScreenGetBufferSizeEx(1); + unsigned char *screenBuffer = MEM1_alloc(screen_buf0_size + screen_buf1_size, 0x100); + char msg[80]; + + OSScreenSetBufferEx(0, screenBuffer); + OSScreenSetBufferEx(1, (screenBuffer + screen_buf0_size)); + OSScreenEnableEx(0, 1); OSScreenEnableEx(1, 1); - + // Render IP selector and check for buttons u_serv_ip ip; - ip.full = ( (192<<24) | (168<<16) | (86<<8) | (186<<0) ); + ip.full = ((192 << 24) | (168 << 16) | (2 << 8) | (18 << 0)); VPADData vpad_data; s32 error; int delay = 0; int gui_mode = 0; + int success = 0; // for exiting the menu with the home button int sel_ip = 3; - + while (1) { - // Refresh GamePad screen + // Refresh TV and GamePad screen + OSScreenFlipBuffersEx(0); OSScreenFlipBuffersEx(1); + OSScreenClearBufferEx(0, 0); OSScreenClearBufferEx(1, 0); - + // Read vpad VPADRead(0, &vpad_data, 1, &error); - + // Title - PRINT_TEXT1(23, 1, "-- geckiine --"); - + PRINT_TEXT2(14, 1, "-- Geckiine + Swap DRC --"); + if (gui_mode == 0) // IP selector { - PRINT_TEXT2(3, 4, " IP : %3d.%3d.%3d.%3d", ip.digit[0], ip.digit[1], ip.digit[2], ip.digit[3]); - PRINT_TEXT1(3, 6, "Use the D-Pad to enter in your computer's IP address,"); - PRINT_TEXT1(3, 7, "then press A to install geckiine."); - PRINT_TEXT1(3, 10, "Press X for credits."); - - PRINT_TEXT1(11 + 4 * sel_ip, 3, "vvv"); + PRINT_TEXT2(0, 4, " IP : %3d.%3d.%3d.%3d", ip.digit[0], ip.digit[1], ip.digit[2], ip.digit[3]); + PRINT_TEXT2(0, 6, "Use the D-Pad to enter in your computer's IP address,"); + PRINT_TEXT2(0, 8, "Press A to install TCPGecko + Cafiine."); + PRINT_TEXT2(0, 9, "Press Y to install TCPGecko only."); + PRINT_TEXT2(0, 10, "Press B to view guide."); + PRINT_TEXT2(0, 11, "Press X for credits."); + PRINT_TEXT2(0, 13, "Press Home to Exit."); + + + PRINT_TEXT2(8 + 4 * sel_ip, 3, "vvv"); } else if (gui_mode == 1) // Credits { - PRINT_TEXT1(3, 4, "* Maschell for HID to VPAD"); - PRINT_TEXT1(3, 5, "* Dimok for function_hooks and the pygecko server"); - PRINT_TEXT1(3, 6, "* brienj for the IP selector and initial UI"); - PRINT_TEXT1(3, 7, "* amiibu for help with the PHP downloader script"); - PRINT_TEXT1(3, 8, "* seresaa for the banner and Geckiine Creator"); - PRINT_TEXT1(3, 9, "* 466 for web hosting"); - PRINT_TEXT1(3, 10, "* /u/MachMatic for the banner background"); - PRINT_TEXT1(3, 13, "Press X to return to the IP selector."); + PRINT_TEXT2(0, 5, "* Maschell for HID to VPAD"); + PRINT_TEXT2(0, 6, "* Dimok for function_hooks and the pygecko server"); + PRINT_TEXT2(0, 7, "* brienj for the IP selector and initial UI"); + PRINT_TEXT2(0, 8, "* amiibu for help with the PHP downloader script"); + PRINT_TEXT2(0, 9, "* seresaa for the banner and Geckiine Creator"); + PRINT_TEXT2(0, 10, "* 466 for web hosting"); + PRINT_TEXT2(0, 11, "* /u/MachMatic for the banner background"); + PRINT_TEXT2(0, 12, "* Yahya14 TBA 2017"); + PRINT_TEXT2(0, 14, "Press X to return to the IP selector."); } - + + else if (gui_mode == 2) // Guide + { + PRINT_TEXT2(0, 2, " ___ ___ "); + PRINT_TEXT2(0, 3, " ------------------------------------- "); + PRINT_TEXT2(0, 3, "/ \\"); + PRINT_TEXT2(0, 4, "| _________________ |"); + PRINT_TEXT2(0, 5, "| _ | | |"); + PRINT_TEXT2(0, 6, "| _| |_ | | O |"); + PRINT_TEXT2(0, 7, "| |_ _| | | O O |"); + PRINT_TEXT2(0, 8, "| |_| | | O |"); + PRINT_TEXT2(0, 9, "| | | + |"); + PRINT_TEXT2(0, 9, "| _________________ |"); + PRINT_TEXT2(0,10, "| ~ - |"); + PRINT_TEXT2(0,11, "|_____________________________________|"); + + PRINT_TEXT2(0, 1, " |||"); + PRINT_TEXT2(0, 2, " vvv"); + PRINT_TEXT2(0,10, " <---"); + + + PRINT_TEXT2(0,13, "Hold L then press Minus to swap screens."); + PRINT_TEXT2(0,14, "Splatoon Only: Press B during a battle."); + PRINT_TEXT2(0, 15, "Press B to return to the IP selector."); + + + } + if ((vpad_data.btns_h & VPAD_BUTTON_A) && gui_mode == 0) { // Set wait message OSScreenClearBufferEx(1, 0); - PRINT_TEXT1(43, 17, "Installing geckiine..."); + PRINT_TEXT2(40, 17, "Installing geckiine..."); + OSScreenFlipBuffersEx(1); + break; + } + else if ((vpad_data.btns_h & VPAD_BUTTON_Y) && gui_mode == 0) + { + // Set wait message + OSScreenClearBufferEx(1, 0); + PRINT_TEXT2(30, 17, "Then no cafiine for you bud..."); + ip.full = 0; OSScreenFlipBuffersEx(1); break; } @@ -168,6 +217,15 @@ int Menu_Main() delay = 100; } } + else if (vpad_data.btns_h & VPAD_BUTTON_B) + { + if (--delay <= 0) + { + // Swap GUI mode + gui_mode = (gui_mode == 0) ? 2 : 0; + delay = 100; + } + } else if ((vpad_data.btns_h & VPAD_BUTTON_LEFT) && gui_mode == 0) { if (--delay <= 0) @@ -176,8 +234,8 @@ int Menu_Main() sel_ip = 3; else sel_ip--; - - delay = 12; + + delay = 8; } } else if ((vpad_data.btns_h & VPAD_BUTTON_RIGHT) && gui_mode == 0) @@ -186,15 +244,31 @@ int Menu_Main() { sel_ip++; sel_ip = sel_ip % 4; - delay = 6; + delay = 8; + } + } + else if ((vpad_data.btns_d & VPAD_BUTTON_UP) && gui_mode == 0) // add large delay at first 1/2 + { + if (--delay <= 0) + { + ip.digit[sel_ip]++; + delay = 10; } } - else if ((vpad_data.btns_h & VPAD_BUTTON_UP) && gui_mode == 0) + else if ((vpad_data.btns_h & VPAD_BUTTON_UP) && gui_mode == 0) // then it gets shorter when holding it 2/2 { if (--delay <= 0) { ip.digit[sel_ip]++; - delay = 6; + delay = 3; + } + } + else if ((vpad_data.btns_d & VPAD_BUTTON_DOWN) && gui_mode == 0) + { + if (--delay <= 0) + { + ip.digit[sel_ip]--; + delay = 10; } } else if ((vpad_data.btns_h & VPAD_BUTTON_DOWN) && gui_mode == 0) @@ -202,15 +276,34 @@ int Menu_Main() if (--delay <= 0) { ip.digit[sel_ip]--; - delay = 6; + delay = 3; } } + else if ((vpad_data.btns_h & VPAD_BUTTON_HOME) && gui_mode == 0) + { + success = -1; + break; + } else { delay = 0; } } - + + MEM1_free(screenBuffer); + screenBuffer = NULL; + + memoryRelease(); + + //return to HBV + if (success == -1) + { + return EXIT_SUCCESS; + } + + SYSLaunchMenu(); + + PatchMethodHooks(); patched = 1; new_addr = ip.full; } diff --git a/src/patcher/function_hooks.c b/src/patcher/function_hooks.c index b5d6451..32a2480 100644 --- a/src/patcher/function_hooks.c +++ b/src/patcher/function_hooks.c @@ -241,15 +241,12 @@ DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) } } - // Checks special equipped pointer - if (*(inkstrikeEq - 0xC) != 0x3F800000) + // checks special equipped pointer + uint32_t* ptr = (uint32_t*)0x106E46E8; + if (buffer->btns_d & VPAD_BUTTON_MINUS && (*ptr > 0x1D000000 && *ptr < 0x28000000)) { - uint32_t firstBase = *(uint32_t*)0x106E46E8; - if (firstBase > 0x1D000000 && firstBase < 0x27000000) - { - inkstrikeEq = (uint32_t*)(firstBase + 0x80); - spTimer = (uint32_t*)(firstBase + 0x80C); - } + inkstrikeEq = (uint32_t*)(*ptr + 0x80); + spTimer = (uint32_t*)(*ptr + 0x808); } } @@ -258,7 +255,7 @@ DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) { drcMode = !drcMode; } - + // disable touchscreen input if the TV is on the DRC if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) {} else @@ -356,8 +353,8 @@ static struct hooks_magic_t { MAKE_MAGIC(FSIsEof, LIB_FS, STATIC_FUNCTION), MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION), MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION), - MAKE_MAGIC(VPADGetTPCalibratedPoint, LIB_VPAD, STATIC_FUNCTION)//, - //MAKE_MAGIC(VPADGetTPCalibratedPointEx, LIB_VPAD, STATIC_FUNCTION) + MAKE_MAGIC(VPADGetTPCalibratedPoint, LIB_VPAD, STATIC_FUNCTION), + MAKE_MAGIC(VPADGetTPCalibratedPointEx, LIB_VPAD, STATIC_FUNCTION) }; diff --git a/src/retain_vars.c b/src/retain_vars.c index 1aa2fab..9e3b78e 100644 --- a/src/retain_vars.c +++ b/src/retain_vars.c @@ -2,6 +2,7 @@ int isSplatoon __attribute__((section(".data"))) = 0; int drcMode __attribute__((section(".data"))) = 0; +int patched __attribute__((section(".data"))) = 0; int screenPressTimeout __attribute__((section(".data"))) = 0; uint32_t* gamemode __attribute__((section(".data"))) = (uint32_t*)0; uint32_t* inkstrikeEq __attribute__((section(".data"))) = (uint32_t*)0x10000000; diff --git a/src/retain_vars.h b/src/retain_vars.h index a76a746..fd58834 100644 --- a/src/retain_vars.h +++ b/src/retain_vars.h @@ -5,6 +5,7 @@ extern int isSplatoon; extern int drcMode; +extern int patched; extern int screenPressTimeout; extern uint32_t* gamemode; extern uint32_t* inkstrikeEq; From 006156f09569400aadca8701eff1037dc58ad086 Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Fri, 30 Jun 2017 22:52:31 -0400 Subject: [PATCH 03/14] Edited some of the menu text --- src/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 2caa858..b8ce8ce 100644 --- a/src/main.c +++ b/src/main.c @@ -141,7 +141,7 @@ int Menu_Main() { PRINT_TEXT2(0, 4, " IP : %3d.%3d.%3d.%3d", ip.digit[0], ip.digit[1], ip.digit[2], ip.digit[3]); PRINT_TEXT2(0, 6, "Use the D-Pad to enter in your computer's IP address,"); - PRINT_TEXT2(0, 8, "Press A to install TCPGecko + Cafiine."); + PRINT_TEXT2(0, 8, "Press A to install TCPGecko + Cafiine. (need server running)"); PRINT_TEXT2(0, 9, "Press Y to install TCPGecko only."); PRINT_TEXT2(0, 10, "Press B to view guide."); PRINT_TEXT2(0, 11, "Press X for credits."); @@ -195,6 +195,7 @@ int Menu_Main() { // Set wait message OSScreenClearBufferEx(1, 0); + OSScreenClearBufferEx(0, 0); PRINT_TEXT2(40, 17, "Installing geckiine..."); OSScreenFlipBuffersEx(1); break; @@ -203,7 +204,8 @@ int Menu_Main() { // Set wait message OSScreenClearBufferEx(1, 0); - PRINT_TEXT2(30, 17, "Then no cafiine for you bud..."); + OSScreenClearBufferEx(0, 0); + PRINT_TEXT2(36, 17, "Installing TCPGecko only..."); ip.full = 0; OSScreenFlipBuffersEx(1); break; From 025849af80aad93c9303905eda5c45e5e8bb6a4f Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Tue, 4 Jul 2017 18:29:57 -0400 Subject: [PATCH 04/14] Fixed cafiine + other minor fixes --- src/dynamic_libs/socket_functions.h | 2 +- src/main.c | 29 ++++++++++++++--------------- src/retain_vars.c | 2 +- src/retain_vars.h | 1 - 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/dynamic_libs/socket_functions.h b/src/dynamic_libs/socket_functions.h index f220599..4aa2daf 100644 --- a/src/dynamic_libs/socket_functions.h +++ b/src/dynamic_libs/socket_functions.h @@ -76,7 +76,7 @@ struct sockaddr char sa_data[14]; }; -unsigned int new_addr; +extern unsigned int new_addr; void InitSocketFunctionPointers(void); void InitAcquireSocket(void); diff --git a/src/main.c b/src/main.c index b8ce8ce..9b4428a 100644 --- a/src/main.c +++ b/src/main.c @@ -73,16 +73,6 @@ int Menu_Main() log_deinit(); return EXIT_RELAUNCH_ON_LOAD; } - /* - if (strlen(cosAppXmlInfoStruct.rpx_name) == 0) - { - log_printf("Returning to the Wii U menu.\n"); - - SYSLaunchMenu(); - - log_deinit(); - return EXIT_RELAUNCH_ON_LOAD; - }*/ // Check for Splatoon (Gambit) if (strcasecmp("Gambit.rpx", cosAppXmlInfoStruct.rpx_name) == 0) @@ -90,6 +80,15 @@ int Menu_Main() log_printf("Splatoon enhanced swapping enabled.\n"); isSplatoon = 1; } + else + { + if (isSplatoon == 1) + { + log_printf("Splatoon enhanced swapping disabled.\n"); + } + + isSplatoon = 0; + } log_printf("Starting the TCPGecko server.\n"); start_pygecko(); @@ -262,7 +261,7 @@ int Menu_Main() if (--delay <= 0) { ip.digit[sel_ip]++; - delay = 3; + delay = 2; } } else if ((vpad_data.btns_d & VPAD_BUTTON_DOWN) && gui_mode == 0) @@ -278,7 +277,7 @@ int Menu_Main() if (--delay <= 0) { ip.digit[sel_ip]--; - delay = 3; + delay = 2; } } else if ((vpad_data.btns_h & VPAD_BUTTON_HOME) && gui_mode == 0) @@ -308,11 +307,11 @@ int Menu_Main() PatchMethodHooks(); patched = 1; new_addr = ip.full; + + log_printf("Returning to application.\n"); + log_deinit(); } - log_printf("Returning to application.\n"); - log_deinit(); - return EXIT_RELAUNCH_ON_LOAD; } diff --git a/src/retain_vars.c b/src/retain_vars.c index 9e3b78e..ba723fc 100644 --- a/src/retain_vars.c +++ b/src/retain_vars.c @@ -3,7 +3,7 @@ int isSplatoon __attribute__((section(".data"))) = 0; int drcMode __attribute__((section(".data"))) = 0; int patched __attribute__((section(".data"))) = 0; -int screenPressTimeout __attribute__((section(".data"))) = 0; +uint32_t new_addr __attribute__((section(".data"))) = 0; uint32_t* gamemode __attribute__((section(".data"))) = (uint32_t*)0; uint32_t* inkstrikeEq __attribute__((section(".data"))) = (uint32_t*)0x10000000; uint32_t* spTimer __attribute__((section(".data"))) = (uint32_t*)0x10000000; \ No newline at end of file diff --git a/src/retain_vars.h b/src/retain_vars.h index fd58834..fbdafe3 100644 --- a/src/retain_vars.h +++ b/src/retain_vars.h @@ -6,7 +6,6 @@ extern int isSplatoon; extern int drcMode; extern int patched; -extern int screenPressTimeout; extern uint32_t* gamemode; extern uint32_t* inkstrikeEq; extern uint32_t* spTimer; From 38b75ed17fefdad5026812116c814e682629fd05 Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Fri, 7 Jul 2017 02:51:57 -0400 Subject: [PATCH 05/14] fixed home menu crash + added procui functions Procui doesn't work for me. Needs to be fixed very soon if possible. --- src/common/common.h | 1 + src/dynamic_libs/procui_functions.c | 21 ++++ src/dynamic_libs/procui_functions.h | 41 ++++++++ src/main.c | 9 +- src/patcher/function_hooks.c | 152 +++++++++++++--------------- src/patcher/function_hooks.h | 1 + 6 files changed, 142 insertions(+), 83 deletions(-) create mode 100644 src/dynamic_libs/procui_functions.c create mode 100644 src/dynamic_libs/procui_functions.h diff --git a/src/common/common.h b/src/common/common.h index 04326ac..4655663 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -26,6 +26,7 @@ extern "C" { #define LIB_NN_ACP 11 #define LIB_SYSHID 12 #define LIB_VPADBASE 13 +#define LIB_PROCUI 14 // functions types #define STATIC_FUNCTION 0 diff --git a/src/dynamic_libs/procui_functions.c b/src/dynamic_libs/procui_functions.c new file mode 100644 index 0000000..16212c7 --- /dev/null +++ b/src/dynamic_libs/procui_functions.c @@ -0,0 +1,21 @@ +#include "os_functions.h" +#include "procui_functions.h" + +unsigned int procui_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, ProcUIInit, ProcUISaveCallbackFunction function); +EXPORT_DECL(void, ProcUIRegisterCallback, int message, ProcUICallbackFunction function, void* data, int priority); + +void InitAcquireProcUI(void) +{ + OSDynLoad_Acquire("proc_ui.rpl", &procui_handle); +} + +void InitProcUIFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + InitAcquireProcUI(); + + OS_FIND_EXPORT(procui_handle, ProcUIInit); + OS_FIND_EXPORT(procui_handle, ProcUIRegisterCallback); +} diff --git a/src/dynamic_libs/procui_functions.h b/src/dynamic_libs/procui_functions.h new file mode 100644 index 0000000..41eb00f --- /dev/null +++ b/src/dynamic_libs/procui_functions.h @@ -0,0 +1,41 @@ +#ifndef __PROCUI_FUNCTIONS_H_ +#define __PROCUI_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum ProcUICallbackType +{ + PROCUI_CALLBACK_ACQUIRE, + PROCUI_CALLBACK_RELEASE, + PROCUI_CALLBACK_EXIT, + PROCUI_CALLBACK_NET_IO_START, + PROCUI_CALLBACK_NET_IO_STOP, + PROCUI_CALLBACK_HOME_BUTTON_DENIED, +} ProcUICallbackType; + +typedef enum ProcUIStatus +{ + PROCUI_STATUS_IN_FOREGROUND, + PROCUI_STATUS_IN_BACKGROUND, + PROCUI_STATUS_RELEASE_FOREGROUND, + PROCUI_STATUS_EXITING, +} ProcUIStatus; + +extern unsigned int procui_handle; + +void InitProcUIFunctionPointers(void); +void InitAcquireProcUI(void); + +typedef void (*ProcUISaveCallbackFunction)(void); +typedef int (*ProcUICallbackFunction)(void*); + +extern void (*ProcUIInit)(ProcUISaveCallbackFunction function); +extern void (*ProcUIRegisterCallback)(int message, ProcUICallbackFunction function, void* data, int priority); + +#ifdef __cplusplus +} +#endif + +#endif // __PROCUI_FUNCTIONS_H_ diff --git a/src/main.c b/src/main.c index 9b4428a..f72bc20 100644 --- a/src/main.c +++ b/src/main.c @@ -10,6 +10,7 @@ #include "dynamic_libs/sys_functions.h" #include "dynamic_libs/fs_functions.h" #include "dynamic_libs/vpad_functions.h" +#include "dynamic_libs/procui_functions.h" #include "utils/logger.h" #include "system/memory.h" #include "common/common.h" @@ -46,6 +47,7 @@ int Menu_Main() InitSysFunctionPointers(); InitFSFunctionPointers(); InitVPadFunctionPointers(); + InitProcUIFunctionPointers(); log_init("192.168.2.18"); @@ -307,11 +309,12 @@ int Menu_Main() PatchMethodHooks(); patched = 1; new_addr = ip.full; - - log_printf("Returning to application.\n"); - log_deinit(); } + log_printf("Returning to application.\n"); + log_printf("De-initializing logging.\n"); + log_deinit(); + return EXIT_RELAUNCH_ON_LOAD; } diff --git a/src/patcher/function_hooks.c b/src/patcher/function_hooks.c index 32a2480..f632684 100644 --- a/src/patcher/function_hooks.c +++ b/src/patcher/function_hooks.c @@ -9,6 +9,7 @@ #include "dynamic_libs/sys_functions.h" #include "dynamic_libs/gx2_functions.h" #include "dynamic_libs/vpad_functions.h" +#include "dynamic_libs/procui_functions.h" #include "kernel/kernel_functions.h" #include "function_hooks.h" #include "utils/logger.h" @@ -25,6 +26,24 @@ res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \ res my_ ## name(__VA_ARGS__) +int home = 1; + +// funcions for procui +int foreground_acquire(void* data) +{ + // reset flag + home = 0; + return 0; +} + +int foreground_release(void* data) +{ + // signal to the thread that the function pointers need to be reacquired + home = 1; + return 0; +} + + DECL(int, FSAInit, void) { if ((int)bss_ptr == 0x0a000000) { memset_bss(); @@ -184,6 +203,17 @@ DECL(int, FSIsEof, void *pClient, void *pCmd, int fd, int error) { return real_FSIsEof(pClient, pCmd, fd, error); } +DECL(void, ProcUIInit, ProcUISaveCallbackFunction function) { + // init ProcUI + real_ProcUIInit(function); + + if (isSplatoon) { + // register callbacks + ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, &foreground_acquire, NULL, 0); + ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, &foreground_release, NULL, 0); + } +} + DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan_target) { // GX2 destinations: @@ -194,8 +224,7 @@ DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan // 0x0 = normal // 0x1 = swap - // the 1st if statement can also FORCE the drcMode to default when inkstrike is activated - + // check drc swap and force the drcMode to default when inkstrike is activated if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) { real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); @@ -217,38 +246,45 @@ DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) { int ret = real_VPADRead(chan, buffer, buffer_size, error); - // check if we should use Splatoon mode controls - if (isSplatoon) - { - if (gamemode == (uint32_t*)0) - { - uint32_t firstBase = *(uint32_t*)0x106A3BA0; - if (firstBase > 0x10000000 && firstBase < 0x11000000) - { - uint32_t secondBase = *(uint32_t*)(firstBase + 0xD074); - if (secondBase > 0x12000000 && secondBase < 0x14000000) - { - gamemode = (uint32_t*)(secondBase + 0x238); - } - } - } - else if (*gamemode != 0xFFFFFFFF) - { - // switch if B is pressed - if (buffer->btns_d & VPAD_BUTTON_B) - { - drcMode = !drcMode; - } - } - + // check if we should use Splatoon mode controls + if (isSplatoon) + { // checks special equipped pointer uint32_t* ptr = (uint32_t*)0x106E46E8; - if (buffer->btns_d & VPAD_BUTTON_MINUS && (*ptr > 0x1D000000 && *ptr < 0x28000000)) + if (*ptr == 0) + { + // prevents the game from crashing + inkstrikeEq = (uint32_t*)0x10000000; + spTimer = (uint32_t*)0x10000000; + } + else if (*ptr > 0x1D000000 && *ptr < 0x28000000) { inkstrikeEq = (uint32_t*)(*ptr + 0x80); spTimer = (uint32_t*)(*ptr + 0x808); } - } + + // enable/disable B switching + if (gamemode == (uint32_t*)0) + { + uint32_t firstBase = *(uint32_t*)0x106A3BA0; + if (firstBase > 0x10000000 && firstBase < 0x11000000) + { + uint32_t secondBase = *(uint32_t*)(firstBase + 0xD074); + if (secondBase > 0x12000000 && secondBase < 0x14000000) + { + gamemode = (uint32_t*)(secondBase + 0x238); + } + } + } + else if (*gamemode != 0xFFFFFFFF) + { + // switch if B is pressed + if (buffer->btns_d & VPAD_BUTTON_B) + { + drcMode = !drcMode; + } + } + } // switch on L and SELECT if (buffer->btns_d & VPAD_BUTTON_MINUS && buffer->btns_h & VPAD_BUTTON_L) @@ -256,68 +292,20 @@ DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) drcMode = !drcMode; } - // disable touchscreen input if the TV is on the DRC - if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) {} - else - { - buffer->tpdata.touched = 0; - buffer->tpdata1.touched = 0; - buffer->tpdata2.touched = 0; - } - return ret; } DECL(void, VPADGetTPCalibratedPoint, int chan, VPADTPData *screen, VPADTPData *raw) { real_VPADGetTPCalibratedPoint(chan, screen, raw); - - // disable touchscreen input if the TV is on the DRC - if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) {} - else - { - screen->touched = 0; - raw->touched = 0; - } -} - -DECL(void, VPADGetTPCalibratedPointEx, int chan, int resolution, VPADTPData *screen, VPADTPData *raw) -{ - real_VPADGetTPCalibratedPointEx(chan, resolution, screen, raw); // disable touchscreen input if the TV is on the DRC - if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) {} + if (drcMode == 0 || (isSplatoon && home && *inkstrikeEq == 2 && *spTimer != 0)) {} else { screen->touched = 0; raw->touched = 0; } - - /* - // check for Splatoon - if (isSplatoon) - { - if (screenPressTimeout != 0) - { - screenPressTimeout--; - } - - // disable touchscreen input if the TV is on the DRC - if (drcMode == 1 && screenPressTimeout == 0) - { - screen->touched = 0; - raw->touched = 0; - } - else - { - // Swap once a touchscreen input is received during a match - if (screen->touched == 1 && gamemode != 0 && *gamemode != 0xFFFFFFFF) - { - drcMode = !drcMode; - screenPressTimeout = 300; - } - } - }*/ } /* ***************************************************************************** @@ -351,10 +339,10 @@ static struct hooks_magic_t { MAKE_MAGIC(FSSetPosFile, LIB_FS, STATIC_FUNCTION), MAKE_MAGIC(FSGetStatFile, LIB_FS, STATIC_FUNCTION), MAKE_MAGIC(FSIsEof, LIB_FS, STATIC_FUNCTION), + MAKE_MAGIC(ProcUIInit, LIB_PROCUI, DYNAMIC_FUNCTION), MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION), MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION), - MAKE_MAGIC(VPADGetTPCalibratedPoint, LIB_VPAD, STATIC_FUNCTION), - MAKE_MAGIC(VPADGetTPCalibratedPointEx, LIB_VPAD, STATIC_FUNCTION) + MAKE_MAGIC(VPADGetTPCalibratedPoint, LIB_VPAD, STATIC_FUNCTION) }; @@ -534,7 +522,11 @@ unsigned int GetAddressOfFunction(const char * functionName,unsigned int library log_printf("FindExport of %s! From LIB_FS\n", functionName); if(coreinit_handle == 0){log_print("LIB_FS not aquired\n"); return 0;} rpl_handle = coreinit_handle; - }else if (library == LIB_GX2){ + }else if (library == LIB_PROCUI) { + log_printf("FindExport of %s! From LIB_PROCUI\n", functionName); + if (vpad_handle == 0) { log_print("LIB_PROCUI not aquired\n"); return 0; } + rpl_handle = procui_handle; + }else if (library == LIB_GX2){ log_printf("FindExport of %s! From LIB_GX2\n", functionName); if(gx2_handle == 0){log_print("LIB_GX2 not aquired\n"); return 0;} rpl_handle = gx2_handle; diff --git a/src/patcher/function_hooks.h b/src/patcher/function_hooks.h index 8b8539b..7dfa387 100644 --- a/src/patcher/function_hooks.h +++ b/src/patcher/function_hooks.h @@ -14,6 +14,7 @@ struct fs_async_t { void *queue; }; +extern int home; void PatchMethodHooks(void); void RestoreInstructions(void); unsigned int GetAddressOfFunction(const char * functionName,unsigned int library); From ab9c876d15503bee1dde12ac3ae394ce2cda2a46 Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Tue, 11 Jul 2017 13:46:22 -0400 Subject: [PATCH 06/14] Moved splatoon patches to another file --- src/main.c | 22 +++++------ src/patcher/function_hooks.c | 41 ++------------------- src/patcher/gambit_functions.c | 67 ++++++++++++++++++++++++++++++++++ src/patcher/gambit_functions.h | 17 +++++++++ src/retain_vars.c | 7 +++- src/retain_vars.h | 5 +++ 6 files changed, 110 insertions(+), 49 deletions(-) create mode 100644 src/patcher/gambit_functions.c create mode 100644 src/patcher/gambit_functions.h diff --git a/src/main.c b/src/main.c index f72bc20..0798ac8 100644 --- a/src/main.c +++ b/src/main.c @@ -136,14 +136,14 @@ int Menu_Main() VPADRead(0, &vpad_data, 1, &error); // Title - PRINT_TEXT2(14, 1, "-- Geckiine + Swap DRC --"); + PRINT_TEXT2(20, 1, "-- Swap DRC --"); if (gui_mode == 0) // IP selector { PRINT_TEXT2(0, 4, " IP : %3d.%3d.%3d.%3d", ip.digit[0], ip.digit[1], ip.digit[2], ip.digit[3]); PRINT_TEXT2(0, 6, "Use the D-Pad to enter in your computer's IP address,"); - PRINT_TEXT2(0, 8, "Press A to install TCPGecko + Cafiine. (need server running)"); - PRINT_TEXT2(0, 9, "Press Y to install TCPGecko only."); + PRINT_TEXT2(0, 8, "Press A to install with TCPGecko."); + PRINT_TEXT2(0, 9, "Press Y to install with TCPGecko + Cafiine. (need server running)"); PRINT_TEXT2(0, 10, "Press B to view guide."); PRINT_TEXT2(0, 11, "Press X for credits."); PRINT_TEXT2(0, 13, "Press Home to Exit."); @@ -161,7 +161,7 @@ int Menu_Main() PRINT_TEXT2(0, 9, "* seresaa for the banner and Geckiine Creator"); PRINT_TEXT2(0, 10, "* 466 for web hosting"); PRINT_TEXT2(0, 11, "* /u/MachMatic for the banner background"); - PRINT_TEXT2(0, 12, "* Yahya14 TBA 2017"); + PRINT_TEXT2(0, 13, "* OatmealDome and Yahya14 for Swap DRC"); PRINT_TEXT2(0, 14, "Press X to return to the IP selector."); } @@ -197,7 +197,8 @@ int Menu_Main() // Set wait message OSScreenClearBufferEx(1, 0); OSScreenClearBufferEx(0, 0); - PRINT_TEXT2(40, 17, "Installing geckiine..."); + PRINT_TEXT2(42, 17, "Installing TCPGecko..."); + ip.full = 0; OSScreenFlipBuffersEx(1); break; } @@ -206,8 +207,7 @@ int Menu_Main() // Set wait message OSScreenClearBufferEx(1, 0); OSScreenClearBufferEx(0, 0); - PRINT_TEXT2(36, 17, "Installing TCPGecko only..."); - ip.full = 0; + PRINT_TEXT2(42, 17, "Installing geckiine..."); OSScreenFlipBuffersEx(1); break; } @@ -309,11 +309,11 @@ int Menu_Main() PatchMethodHooks(); patched = 1; new_addr = ip.full; + + log_printf("Returning to application.\n"); + log_printf("De-initializing logging.\n"); + log_deinit(); } - - log_printf("Returning to application.\n"); - log_printf("De-initializing logging.\n"); - log_deinit(); return EXIT_RELAUNCH_ON_LOAD; } diff --git a/src/patcher/function_hooks.c b/src/patcher/function_hooks.c index f632684..ecba210 100644 --- a/src/patcher/function_hooks.c +++ b/src/patcher/function_hooks.c @@ -15,6 +15,7 @@ #include "utils/logger.h" #include "cafiine/cafiine.h" #include "retain_vars.h" +#include "gambit_functions.h" #define LIB_CODE_RW_BASE_OFFSET 0xC1000000 #define CODE_RW_BASE_OFFSET 0x00000000 @@ -225,7 +226,7 @@ DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan // 0x1 = swap // check drc swap and force the drcMode to default when inkstrike is activated - if (drcMode == 0 || (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0)) + if (drcMode == 0 || gambitDRC()) { real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); } @@ -249,41 +250,7 @@ DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) // check if we should use Splatoon mode controls if (isSplatoon) { - // checks special equipped pointer - uint32_t* ptr = (uint32_t*)0x106E46E8; - if (*ptr == 0) - { - // prevents the game from crashing - inkstrikeEq = (uint32_t*)0x10000000; - spTimer = (uint32_t*)0x10000000; - } - else if (*ptr > 0x1D000000 && *ptr < 0x28000000) - { - inkstrikeEq = (uint32_t*)(*ptr + 0x80); - spTimer = (uint32_t*)(*ptr + 0x808); - } - - // enable/disable B switching - if (gamemode == (uint32_t*)0) - { - uint32_t firstBase = *(uint32_t*)0x106A3BA0; - if (firstBase > 0x10000000 && firstBase < 0x11000000) - { - uint32_t secondBase = *(uint32_t*)(firstBase + 0xD074); - if (secondBase > 0x12000000 && secondBase < 0x14000000) - { - gamemode = (uint32_t*)(secondBase + 0x238); - } - } - } - else if (*gamemode != 0xFFFFFFFF) - { - // switch if B is pressed - if (buffer->btns_d & VPAD_BUTTON_B) - { - drcMode = !drcMode; - } - } + gambitPatcher(buffer); } // switch on L and SELECT @@ -300,7 +267,7 @@ DECL(void, VPADGetTPCalibratedPoint, int chan, VPADTPData *screen, VPADTPData *r real_VPADGetTPCalibratedPoint(chan, screen, raw); // disable touchscreen input if the TV is on the DRC - if (drcMode == 0 || (isSplatoon && home && *inkstrikeEq == 2 && *spTimer != 0)) {} + if (drcMode == 0 || gambitDRC()) {} else { screen->touched = 0; diff --git a/src/patcher/gambit_functions.c b/src/patcher/gambit_functions.c new file mode 100644 index 0000000..c9afc1f --- /dev/null +++ b/src/patcher/gambit_functions.c @@ -0,0 +1,67 @@ +#include "dynamic_libs/vpad_functions.h" +#include "retain_vars.h" +#include "utils/logger.h" +#include "gambit_functions.h" + +unsigned int PCoord[3][3]; + +uint32_t* ptr = (uint32_t*)0x106E46E8; +uint32_t* ptr2 = (uint32_t*)0x106E4DA8; + + +int gambitDRC() +{ + if (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0) + return 1; + else + return 0; +} + +void gambitPatcher(VPADData *buffer) +{ + // prevents the game from crashing + if (*ptr2 < 0x1D000000) + { + inkstrikeEq = (uint32_t*)0x10000000; + spTimer = (uint32_t*)0x10000000; + } + else + { + // define pointers + inkstrikeEq = (uint32_t*)(*ptr + 0x80); + spTimer = (uint32_t*)(*ptr + 0x808); + + // switch if B is pressed in non-menu areas + if (buffer->btns_d & VPAD_BUTTON_B) + { + drcMode = !drcMode; + } + + ////DEV + int j = 0; + // find team side for each player + // you + uint32_t* teamYou = (uint32_t*)(*ptr + 0x2C); + + // other + for (int i = 0; i < 8; i++) + { + uint32_t* pbase = (uint32_t*)(*ptr2 + 0x56C + (4 * i)); + uint32_t* team = (uint32_t*)(*pbase + 0x2C); + + // add allies' coords into an array + if (*team == teamYou && *ptr != *pbase) + { + for (int k = 0; k < 3; k++) + { + PCoord[j][k] = *pbase + 0x248 + (4 * k); + } + + j++; + + } + } + + //// + } +} diff --git a/src/patcher/gambit_functions.h b/src/patcher/gambit_functions.h new file mode 100644 index 0000000..ae4ec66 --- /dev/null +++ b/src/patcher/gambit_functions.h @@ -0,0 +1,17 @@ +#ifndef _GAMBIT_FUNCTIONS_H_ +#define _GAMBIT_FUNCTIONS_H_ + +#include "dynamic_libs/vpad_functions.h" + +#ifdef __cplusplus +extern "C" { +#endif + + extern void gambitPatcher(VPADData *buffer); + extern int gambitDRC(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _FS_H */ diff --git a/src/retain_vars.c b/src/retain_vars.c index ba723fc..52dbb6e 100644 --- a/src/retain_vars.c +++ b/src/retain_vars.c @@ -4,6 +4,11 @@ int isSplatoon __attribute__((section(".data"))) = 0; int drcMode __attribute__((section(".data"))) = 0; int patched __attribute__((section(".data"))) = 0; uint32_t new_addr __attribute__((section(".data"))) = 0; + +// for Splatoon uint32_t* gamemode __attribute__((section(".data"))) = (uint32_t*)0; uint32_t* inkstrikeEq __attribute__((section(".data"))) = (uint32_t*)0x10000000; -uint32_t* spTimer __attribute__((section(".data"))) = (uint32_t*)0x10000000; \ No newline at end of file +uint32_t* spTimer __attribute__((section(".data"))) = (uint32_t*)0x10000000; + +uint32_t incrementVal __attribute__((section(".data"))) = (uint32_t)0; +uint32_t* incrementPtr __attribute__((section(".data"))) = (uint32_t*)0x10000000; \ No newline at end of file diff --git a/src/retain_vars.h b/src/retain_vars.h index fbdafe3..4b14079 100644 --- a/src/retain_vars.h +++ b/src/retain_vars.h @@ -6,8 +6,13 @@ extern int isSplatoon; extern int drcMode; extern int patched; + +// for Splatoon extern uint32_t* gamemode; extern uint32_t* inkstrikeEq; extern uint32_t* spTimer; +extern uint32_t incrementVal; +extern uint32_t* incrementPtr; + #endif // _RETAIN_VARS_H_ \ No newline at end of file From 30f6735ecb611a458f6f47d83819c9b62cb11cb7 Mon Sep 17 00:00:00 2001 From: Yahya Date: Tue, 11 Jul 2017 14:47:00 -0400 Subject: [PATCH 07/14] gambit_function: Reverted B button switching code --- src/patcher/gambit_functions.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/patcher/gambit_functions.c b/src/patcher/gambit_functions.c index c9afc1f..1f78b78 100644 --- a/src/patcher/gambit_functions.c +++ b/src/patcher/gambit_functions.c @@ -31,10 +31,25 @@ void gambitPatcher(VPADData *buffer) inkstrikeEq = (uint32_t*)(*ptr + 0x80); spTimer = (uint32_t*)(*ptr + 0x808); - // switch if B is pressed in non-menu areas - if (buffer->btns_d & VPAD_BUTTON_B) + if (gamemode == (uint32_t*)0) { - drcMode = !drcMode; + uint32_t firstBase = *(uint32_t*)0x106A3BA0; + if (firstBase > 0x10000000 && firstBase < 0x11000000) + { + uint32_t secondBase = *(uint32_t*)(firstBase + 0xD074); + if (secondBase > 0x12000000 && secondBase < 0x14000000) + { + gamemode = (uint32_t*)(secondBase + 0x238); + } + } + } + else if (*gamemode != 0xFFFFFFFF) + { + // switch if B is pressed + if (buffer->btns_d & VPAD_BUTTON_B) + { + drcMode = !drcMode; + } } ////DEV From 5acde3d171e677fbe28951c45777220de5dfb64a Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Tue, 11 Jul 2017 14:55:22 -0400 Subject: [PATCH 08/14] gambit_function: commented out unfinished code --- src/patcher/gambit_functions.c | 3 ++- src/patcher/gambit_functions.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/patcher/gambit_functions.c b/src/patcher/gambit_functions.c index 1f78b78..8df265e 100644 --- a/src/patcher/gambit_functions.c +++ b/src/patcher/gambit_functions.c @@ -52,6 +52,7 @@ void gambitPatcher(VPADData *buffer) } } + /* ////DEV int j = 0; // find team side for each player @@ -76,7 +77,7 @@ void gambitPatcher(VPADData *buffer) } } - + */ //// } } diff --git a/src/patcher/gambit_functions.h b/src/patcher/gambit_functions.h index ae4ec66..0e97590 100644 --- a/src/patcher/gambit_functions.h +++ b/src/patcher/gambit_functions.h @@ -14,4 +14,4 @@ extern "C" { } #endif -#endif /* _FS_H */ +#endif /* _GAMBIT_FUNCTIONS_H_ */ From 069583053174944402c4543b65fd1b773131c38c Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Fri, 14 Jul 2017 18:44:54 -0400 Subject: [PATCH 09/14] Large chunky update. Read description. +Implemented sensor bar switching +Splatoon: Implemented super jump to team with A + D-Pad + Code clean up, improvements, and performance improvements --- src/dynamic_libs/vpad_functions.c | 4 +- src/dynamic_libs/vpad_functions.h | 1 + src/main.c | 11 +- src/patcher/function_hooks.c | 91 ++++++----------- src/patcher/function_hooks.h | 2 +- src/patcher/gambit_functions.c | 162 +++++++++++++++++++++--------- src/patcher/gambit_functions.h | 15 ++- 7 files changed, 170 insertions(+), 116 deletions(-) diff --git a/src/dynamic_libs/vpad_functions.c b/src/dynamic_libs/vpad_functions.c index 17b6e8c..e303898 100644 --- a/src/dynamic_libs/vpad_functions.c +++ b/src/dynamic_libs/vpad_functions.c @@ -35,6 +35,7 @@ EXPORT_DECL(void, VPADGetTPCalibratedPoint, int chan, VPADTPData *screen, VPADTP EXPORT_DECL(void, VPADGetTPCalibratedPointEx, int chan, int resolution, VPADTPData *screen, VPADTPData *raw); EXPORT_DECL(int, VPADBASEGetMotorOnRemainingCount, int padnum); EXPORT_DECL(int, VPADBASESetMotorOnRemainingCount, int padnum, int counter); +EXPORT_DECL(void, VPADSetSensorBar, s32 chan, bool on); void InitAcquireVPad(void) { @@ -53,7 +54,8 @@ void InitVPadFunctionPointers(void) OS_FIND_EXPORT(vpad_handle, VPADGetLcdMode); OS_FIND_EXPORT(vpad_handle, VPADSetLcdMode); OS_FIND_EXPORT(vpad_handle, VPADGetTPCalibratedPoint); - OS_FIND_EXPORT(vpad_handle, VPADGetTPCalibratedPointEx); + OS_FIND_EXPORT(vpad_handle, VPADGetTPCalibratedPointEx); + OS_FIND_EXPORT(vpad_handle, VPADSetSensorBar); OS_FIND_EXPORT(vpadbase_handle, VPADBASEGetMotorOnRemainingCount); OS_FIND_EXPORT(vpadbase_handle, VPADBASESetMotorOnRemainingCount); } diff --git a/src/dynamic_libs/vpad_functions.h b/src/dynamic_libs/vpad_functions.h index b4a6d95..e868579 100644 --- a/src/dynamic_libs/vpad_functions.h +++ b/src/dynamic_libs/vpad_functions.h @@ -108,6 +108,7 @@ extern void (* VPADGetTPCalibratedPoint)(int chan, VPADTPData *screen, VPADTPDat extern void (* VPADGetTPCalibratedPointEx)(int chan, int resolution, VPADTPData *screen, VPADTPData *raw); extern int (* VPADBASEGetMotorOnRemainingCount)(int lcdmode); extern int (* VPADBASESetMotorOnRemainingCount)(int lcdmode,int counter); +extern void (* VPADSetSensorBar)(s32 chan, bool on); #ifdef __cplusplus } diff --git a/src/main.c b/src/main.c index 0798ac8..9dded5d 100644 --- a/src/main.c +++ b/src/main.c @@ -10,7 +10,6 @@ #include "dynamic_libs/sys_functions.h" #include "dynamic_libs/fs_functions.h" #include "dynamic_libs/vpad_functions.h" -#include "dynamic_libs/procui_functions.h" #include "utils/logger.h" #include "system/memory.h" #include "common/common.h" @@ -47,7 +46,6 @@ int Menu_Main() InitSysFunctionPointers(); InitFSFunctionPointers(); InitVPadFunctionPointers(); - InitProcUIFunctionPointers(); log_init("192.168.2.18"); @@ -68,6 +66,8 @@ int Menu_Main() "bl memset\n" ); + PatchMethodHooks(); + if (strcasecmp("men.rpx", cosAppXmlInfoStruct.rpx_name) == 0) { log_printf("Wii U menu started, exiting.\n"); @@ -84,12 +84,11 @@ int Menu_Main() } else { - if (isSplatoon == 1) + if (isSplatoon == 1 && strcasecmp("miiverse_post.rpx", cosAppXmlInfoStruct.rpx_name) != 0) { log_printf("Splatoon enhanced swapping disabled.\n"); + isSplatoon = 0; } - - isSplatoon = 0; } log_printf("Starting the TCPGecko server.\n"); @@ -306,7 +305,7 @@ int Menu_Main() SYSLaunchMenu(); - PatchMethodHooks(); + RestoreInstructions(); patched = 1; new_addr = ip.full; diff --git a/src/patcher/function_hooks.c b/src/patcher/function_hooks.c index ecba210..99238b7 100644 --- a/src/patcher/function_hooks.c +++ b/src/patcher/function_hooks.c @@ -9,7 +9,6 @@ #include "dynamic_libs/sys_functions.h" #include "dynamic_libs/gx2_functions.h" #include "dynamic_libs/vpad_functions.h" -#include "dynamic_libs/procui_functions.h" #include "kernel/kernel_functions.h" #include "function_hooks.h" #include "utils/logger.h" @@ -27,23 +26,7 @@ res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \ res my_ ## name(__VA_ARGS__) -int home = 1; - -// funcions for procui -int foreground_acquire(void* data) -{ - // reset flag - home = 0; - return 0; -} - -int foreground_release(void* data) -{ - // signal to the thread that the function pointers need to be reacquired - home = 1; - return 0; -} - +int swapForce = 0; DECL(int, FSAInit, void) { if ((int)bss_ptr == 0x0a000000) { @@ -204,17 +187,11 @@ DECL(int, FSIsEof, void *pClient, void *pCmd, int fd, int error) { return real_FSIsEof(pClient, pCmd, fd, error); } -DECL(void, ProcUIInit, ProcUISaveCallbackFunction function) { - // init ProcUI - real_ProcUIInit(function); - - if (isSplatoon) { - // register callbacks - ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, &foreground_acquire, NULL, 0); - ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, &foreground_release, NULL, 0); - } +DECL(void, VPADSetSensorBar, s32 chan, bool on) { + real_VPADSetSensorBar(chan, on); } + DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan_target) { // GX2 destinations: @@ -226,52 +203,54 @@ DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan // 0x1 = swap // check drc swap and force the drcMode to default when inkstrike is activated - if (drcMode == 0 || gambitDRC()) + if (drcMode == 0 || swapForce) { real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); } else { - if (scan_target == 0x1) - { - real_GX2CopyColorBufferToScanBuffer(colorBuffer, 0x4); - } - else if (scan_target == 0x4) - { - real_GX2CopyColorBufferToScanBuffer(colorBuffer, 0x1); - } + switch (scan_target) + { + case 0x1: + real_GX2CopyColorBufferToScanBuffer(colorBuffer, 0x4); + break; + case 0x4: + real_GX2CopyColorBufferToScanBuffer(colorBuffer, 0x1); + break; + } } } DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) { - int ret = real_VPADRead(chan, buffer, buffer_size, error); - - // check if we should use Splatoon mode controls - if (isSplatoon) - { - gambitPatcher(buffer); - } // switch on L and SELECT if (buffer->btns_d & VPAD_BUTTON_MINUS && buffer->btns_h & VPAD_BUTTON_L) { drcMode = !drcMode; + log_printf("isSplatoon Address: %p\n", (void*)&isSplatoon); + // enable/disable sensor bar + VPADSetSensorBar(chan, drcMode); } - return ret; + // patches splatoon enhanced controls + if (isSplatoon) + { + gambitPatches(buffer); + gambitDRC(); + } + + return real_VPADRead(chan, buffer, buffer_size, error); } DECL(void, VPADGetTPCalibratedPoint, int chan, VPADTPData *screen, VPADTPData *raw) { real_VPADGetTPCalibratedPoint(chan, screen, raw); - // disable touchscreen input if the TV is on the DRC - if (drcMode == 0 || gambitDRC()) {} - else + if (isSplatoon) { - screen->touched = 0; - raw->touched = 0; + // handles modified touch input for super jumps + gambitTouch(screen); } } @@ -306,10 +285,10 @@ static struct hooks_magic_t { MAKE_MAGIC(FSSetPosFile, LIB_FS, STATIC_FUNCTION), MAKE_MAGIC(FSGetStatFile, LIB_FS, STATIC_FUNCTION), MAKE_MAGIC(FSIsEof, LIB_FS, STATIC_FUNCTION), - MAKE_MAGIC(ProcUIInit, LIB_PROCUI, DYNAMIC_FUNCTION), - MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION), - MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION), - MAKE_MAGIC(VPADGetTPCalibratedPoint, LIB_VPAD, STATIC_FUNCTION) + MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION), + MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION), + MAKE_MAGIC(VPADGetTPCalibratedPoint, LIB_VPAD, STATIC_FUNCTION), + MAKE_MAGIC(VPADSetSensorBar, LIB_VPAD, STATIC_FUNCTION) }; @@ -489,11 +468,7 @@ unsigned int GetAddressOfFunction(const char * functionName,unsigned int library log_printf("FindExport of %s! From LIB_FS\n", functionName); if(coreinit_handle == 0){log_print("LIB_FS not aquired\n"); return 0;} rpl_handle = coreinit_handle; - }else if (library == LIB_PROCUI) { - log_printf("FindExport of %s! From LIB_PROCUI\n", functionName); - if (vpad_handle == 0) { log_print("LIB_PROCUI not aquired\n"); return 0; } - rpl_handle = procui_handle; - }else if (library == LIB_GX2){ + }else if (library == LIB_GX2){ log_printf("FindExport of %s! From LIB_GX2\n", functionName); if(gx2_handle == 0){log_print("LIB_GX2 not aquired\n"); return 0;} rpl_handle = gx2_handle; diff --git a/src/patcher/function_hooks.h b/src/patcher/function_hooks.h index 7dfa387..f5061c2 100644 --- a/src/patcher/function_hooks.h +++ b/src/patcher/function_hooks.h @@ -14,7 +14,7 @@ struct fs_async_t { void *queue; }; -extern int home; +int swapForce; void PatchMethodHooks(void); void RestoreInstructions(void); unsigned int GetAddressOfFunction(const char * functionName,unsigned int library); diff --git a/src/patcher/gambit_functions.c b/src/patcher/gambit_functions.c index 8df265e..f29b24c 100644 --- a/src/patcher/gambit_functions.c +++ b/src/patcher/gambit_functions.c @@ -1,26 +1,127 @@ +#include +#include #include "dynamic_libs/vpad_functions.h" #include "retain_vars.h" #include "utils/logger.h" #include "gambit_functions.h" - -unsigned int PCoord[3][3]; +#include "function_hooks.h" uint32_t* ptr = (uint32_t*)0x106E46E8; uint32_t* ptr2 = (uint32_t*)0x106E4DA8; +bool AButton = 0; +int touchVal = 0; +void gambitDRC() +{ + if (*inkstrikeEq == 2 && *spTimer != 0) + swapForce = 1; + else if (AButton) + swapForce = 1; + else + swapForce = 0; +} -int gambitDRC() +void gambitJump(VPADData *buffer) { - if (isSplatoon && *inkstrikeEq == 2 && *spTimer != 0) - return 1; + + // define gamemode pointer + if (gamemode == (uint32_t*)0) + { + uint32_t firstBase = *(uint32_t*)0x106A3BA0; + if (firstBase > 0x10000000 && firstBase < 0x11000000) + { + uint32_t secondBase = *(uint32_t*)(firstBase + 0xD074); + if (secondBase > 0x12000000 && secondBase < 0x14000000) + { + gamemode = (uint32_t*)(secondBase + 0x238); + } + } + } + + if (*gamemode != 0xFFFFFFFF) + { + if (buffer->btns_h & VPAD_BUTTON_A) + { + // force default swap + AButton = true; + + if (buffer->btns_h & VPAD_BUTTON_LEFT) + { + touchVal = D_LEFT; + } + else if (buffer->btns_h & VPAD_BUTTON_UP) + { + touchVal = D_UP; + } + else if (buffer->btns_h & VPAD_BUTTON_RIGHT) + { + touchVal = D_RIGHT; + } + else if (buffer->btns_h & VPAD_BUTTON_DOWN) + { + touchVal = D_DOWN; + } + else + { + touchVal = D_NEUTRAL; + } + } + else + { + AButton = false; + touchVal = D_NEUTRAL; + } + } else - return 0; + { + AButton = false; + touchVal = D_NEUTRAL; + } +} + +void gambitTouch(VPADTPData *screen) +{ + switch (touchVal) + { + case D_LEFT: + screen->x = 1080; + screen->y = 130; + screen->touched = 1; + screen->invalid = 0; + break; + case D_UP: + screen->x = 1080; + screen->y = 290; + screen->touched = 1; + screen->invalid = 0; + break; + case D_RIGHT: + screen->x = 1080; + screen->y = 450; + screen->touched = 1; + screen->invalid = 0; + break; + case D_DOWN: + screen->x = 1170; + screen->y = 625; + screen->touched = 1; + screen->invalid = 0; + break; + case D_NEUTRAL: + // disable touchscreen input if the TV is on the DRC for Splatoon enhanced controls + if ((drcMode == 0 || swapForce)) {} + else if (*ptr > 0x10000000) + { + screen->touched = 0; + } + break; + } } -void gambitPatcher(VPADData *buffer) +void gambitPatches(VPADData *buffer) { // prevents the game from crashing - if (*ptr2 < 0x1D000000) + if (*ptr < 0x1C000000) { inkstrikeEq = (uint32_t*)0x10000000; spTimer = (uint32_t*)0x10000000; @@ -31,53 +132,18 @@ void gambitPatcher(VPADData *buffer) inkstrikeEq = (uint32_t*)(*ptr + 0x80); spTimer = (uint32_t*)(*ptr + 0x808); - if (gamemode == (uint32_t*)0) - { - uint32_t firstBase = *(uint32_t*)0x106A3BA0; - if (firstBase > 0x10000000 && firstBase < 0x11000000) - { - uint32_t secondBase = *(uint32_t*)(firstBase + 0xD074); - if (secondBase > 0x12000000 && secondBase < 0x14000000) - { - gamemode = (uint32_t*)(secondBase + 0x238); - } - } - } - else if (*gamemode != 0xFFFFFFFF) + if (*ptr2 > 0x1C000000) { // switch if B is pressed if (buffer->btns_d & VPAD_BUTTON_B) { drcMode = !drcMode; - } - } - - /* - ////DEV - int j = 0; - // find team side for each player - // you - uint32_t* teamYou = (uint32_t*)(*ptr + 0x2C); - - // other - for (int i = 0; i < 8; i++) - { - uint32_t* pbase = (uint32_t*)(*ptr2 + 0x56C + (4 * i)); - uint32_t* team = (uint32_t*)(*pbase + 0x2C); - - // add allies' coords into an array - if (*team == teamYou && *ptr != *pbase) - { - for (int k = 0; k < 3; k++) - { - PCoord[j][k] = *pbase + 0x248 + (4 * k); - } - - j++; + // enable/disable sensor bar + VPADSetSensorBar(0, drcMode); } + + gambitJump(buffer); } - */ - //// } } diff --git a/src/patcher/gambit_functions.h b/src/patcher/gambit_functions.h index 0e97590..5b5d1c2 100644 --- a/src/patcher/gambit_functions.h +++ b/src/patcher/gambit_functions.h @@ -7,8 +7,19 @@ extern "C" { #endif - extern void gambitPatcher(VPADData *buffer); - extern int gambitDRC(void); + typedef enum GambitDPAD + { + D_NEUTRAL, + D_LEFT, + D_UP, + D_RIGHT, + D_DOWN + } GambitDPAD; + + extern void gambitDRC(void); + extern void gambitJump(VPADData *buffer); + extern void gambitTouch(VPADTPData *screen); + extern void gambitPatches(VPADData *buffer); #ifdef __cplusplus } From 438d312e3b90f5a34f194a46a72afc76495a16a3 Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Fri, 14 Jul 2017 23:46:23 -0400 Subject: [PATCH 10/14] Fixed important commit bug --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 9dded5d..45c788c 100644 --- a/src/main.c +++ b/src/main.c @@ -300,12 +300,12 @@ int Menu_Main() //return to HBV if (success == -1) { + RestoreInstructions(); return EXIT_SUCCESS; } SYSLaunchMenu(); - RestoreInstructions(); patched = 1; new_addr = ip.full; From d45cfe3f482b172042bd79594556bb85bff0705a Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Sat, 15 Jul 2017 01:30:00 -0400 Subject: [PATCH 11/14] Added a boot message for Splatoon --- src/main.c | 78 ++++++++++++++++-------- src/patcher/gambit_functions.c | 108 +++++++++++++++------------------ 2 files changed, 102 insertions(+), 84 deletions(-) diff --git a/src/main.c b/src/main.c index 45c788c..d36736a 100644 --- a/src/main.c +++ b/src/main.c @@ -31,7 +31,58 @@ typedef union u_serv_ip uint32_t full; } u_serv_ip; -//static unsigned int patched = 0; +void gambitScreen() +{ + memoryInitialize(); + // Init screen and screen buffers + OSScreenInit(); + int screen_buf0_size = OSScreenGetBufferSizeEx(0); + int screen_buf1_size = OSScreenGetBufferSizeEx(1); + unsigned char *screenBuffer = MEM1_alloc(screen_buf0_size + screen_buf1_size, 0x100); + char msg[80]; + + OSScreenSetBufferEx(0, screenBuffer); + OSScreenSetBufferEx(1, (screenBuffer + screen_buf0_size)); + + OSScreenEnableEx(0, 1); + OSScreenEnableEx(1, 1); + + //OSScreenClearBufferEx(1, 0); + //OSScreenClearBufferEx(0, 0); + PRINT_TEXT2(0, 1, "Splatoon detected! Enhancing swap controls..."); + PRINT_TEXT2(2, 3, "Tips:"); + PRINT_TEXT2(2, 5, "Press B to switch screens except in-game menus."); + PRINT_TEXT2(2, 6, "Hold A + D-PAD to super jump to a teammate in a match."); + + PRINT_TEXT2(10, 9, " Teammate 2"); + PRINT_TEXT2(10,10, " _ "); + PRINT_TEXT2(10,11, " _| |_"); + PRINT_TEXT2(10,12, "Teammate 1 |_ _| Teammate 3"); + PRINT_TEXT2(10,13, " |_|"); + PRINT_TEXT2(10,16, " Spawn Point"); + + PRINT_TEXT2(50, 8, " ____________"); + PRINT_TEXT2(50, 9, "| Teammate 1 |"); + PRINT_TEXT2(50, 9, " ____________"); + PRINT_TEXT2(50, 10, " ____________"); + PRINT_TEXT2(50, 11, "| Teammate 2 |"); + PRINT_TEXT2(50, 11, " ____________"); + PRINT_TEXT2(50, 12, " ____________"); + PRINT_TEXT2(50, 13, "| Teammate 3 |"); + PRINT_TEXT2(50, 13, " ____________"); + PRINT_TEXT2(50, 14, " _______"); + PRINT_TEXT2(50, 15, "| Spawn |"); + PRINT_TEXT2(50, 16, "| Point |"); + PRINT_TEXT2(50, 16, " _______"); + + OSScreenFlipBuffersEx(1); + + sleep(1); + MEM1_free(screenBuffer); + screenBuffer = NULL; + + memoryRelease(); +} /* Entry point */ int Menu_Main() @@ -71,7 +122,6 @@ int Menu_Main() if (strcasecmp("men.rpx", cosAppXmlInfoStruct.rpx_name) == 0) { log_printf("Wii U menu started, exiting.\n"); - log_deinit(); return EXIT_RELAUNCH_ON_LOAD; } @@ -80,6 +130,7 @@ int Menu_Main() if (strcasecmp("Gambit.rpx", cosAppXmlInfoStruct.rpx_name) == 0) { log_printf("Splatoon enhanced swapping enabled.\n"); + gambitScreen(); isSplatoon = 1; } else @@ -185,7 +236,6 @@ int Menu_Main() PRINT_TEXT2(0,13, "Hold L then press Minus to swap screens."); - PRINT_TEXT2(0,14, "Splatoon Only: Press B during a battle."); PRINT_TEXT2(0, 15, "Press B to return to the IP selector."); @@ -317,27 +367,5 @@ int Menu_Main() return EXIT_RELAUNCH_ON_LOAD; } -// clear both buffers -void clearScreen() -{ - int i; - for (i = 0; i < 2; i++) - { - int screen_buf0_size = OSScreenGetBufferSizeEx(0); - int screen_buf1_size = OSScreenGetBufferSizeEx(1); - - // Clear screens - OSScreenClearBufferEx(0, 0); - OSScreenClearBufferEx(1, 0); - - // Flush the cache - DCFlushRange((void *)0xF4000000, screen_buf0_size); - DCFlushRange((void *)0xF4000000 + screen_buf0_size, screen_buf1_size); - - // Flip buffers - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); - } -} diff --git a/src/patcher/gambit_functions.c b/src/patcher/gambit_functions.c index f29b24c..6a7c2f4 100644 --- a/src/patcher/gambit_functions.c +++ b/src/patcher/gambit_functions.c @@ -21,64 +21,6 @@ void gambitDRC() swapForce = 0; } -void gambitJump(VPADData *buffer) -{ - - // define gamemode pointer - if (gamemode == (uint32_t*)0) - { - uint32_t firstBase = *(uint32_t*)0x106A3BA0; - if (firstBase > 0x10000000 && firstBase < 0x11000000) - { - uint32_t secondBase = *(uint32_t*)(firstBase + 0xD074); - if (secondBase > 0x12000000 && secondBase < 0x14000000) - { - gamemode = (uint32_t*)(secondBase + 0x238); - } - } - } - - if (*gamemode != 0xFFFFFFFF) - { - if (buffer->btns_h & VPAD_BUTTON_A) - { - // force default swap - AButton = true; - - if (buffer->btns_h & VPAD_BUTTON_LEFT) - { - touchVal = D_LEFT; - } - else if (buffer->btns_h & VPAD_BUTTON_UP) - { - touchVal = D_UP; - } - else if (buffer->btns_h & VPAD_BUTTON_RIGHT) - { - touchVal = D_RIGHT; - } - else if (buffer->btns_h & VPAD_BUTTON_DOWN) - { - touchVal = D_DOWN; - } - else - { - touchVal = D_NEUTRAL; - } - } - else - { - AButton = false; - touchVal = D_NEUTRAL; - } - } - else - { - AButton = false; - touchVal = D_NEUTRAL; - } -} - void gambitTouch(VPADTPData *screen) { switch (touchVal) @@ -129,9 +71,23 @@ void gambitPatches(VPADData *buffer) else { // define pointers + if (gamemode == (uint32_t*)0) + { + uint32_t firstBase = *(uint32_t*)0x106A3BA0; + if (firstBase > 0x10000000 && firstBase < 0x11000000) + { + uint32_t secondBase = *(uint32_t*)(firstBase + 0xD074); + if (secondBase > 0x12000000 && secondBase < 0x14000000) + { + gamemode = (uint32_t*)(secondBase + 0x238); + } + } + } + inkstrikeEq = (uint32_t*)(*ptr + 0x80); spTimer = (uint32_t*)(*ptr + 0x808); + // check if in-game menu is up if (*ptr2 > 0x1C000000) { // switch if B is pressed @@ -143,7 +99,41 @@ void gambitPatches(VPADData *buffer) VPADSetSensorBar(0, drcMode); } - gambitJump(buffer); + // force temporary default swap in a match + if (buffer->btns_h & VPAD_BUTTON_A) + { + if (*gamemode != 0xFFFFFFFF) + { + AButton = true; + + // super jumping with D-Pad + if (buffer->btns_h & VPAD_BUTTON_LEFT) + { + touchVal = D_LEFT; + } + else if (buffer->btns_h & VPAD_BUTTON_UP) + { + touchVal = D_UP; + } + else if (buffer->btns_h & VPAD_BUTTON_RIGHT) + { + touchVal = D_RIGHT; + } + else if (buffer->btns_h & VPAD_BUTTON_DOWN) + { + touchVal = D_DOWN; + } + else + { + touchVal = D_NEUTRAL; + } + } + } + else + { + AButton = false; + touchVal = D_NEUTRAL; + } } } } From 6e7f8301dd2395d4f34911fabe6ac1885fb7f978 Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Mon, 17 Jul 2017 01:40:08 -0400 Subject: [PATCH 12/14] scripted the README + other small changes + Makefile now compiles it to "swapdrc" --- Makefile | 2 +- README.md | 107 +++++++++++++++++++++++++---------- src/main.h | 1 - src/patcher/function_hooks.c | 1 - 4 files changed, 79 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index c3f80a9..4b63073 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ export OBJCOPY := $(PREFIX)objcopy # SOURCES is a list of directories containing source code # INCLUDES is a list of directories containing extra header files #--------------------------------------------------------------------------------- -TARGET := geckiine +TARGET := swapdrc BUILD := build BUILD_DBG := $(TARGET)_dbg SOURCES := src \ diff --git a/README.md b/README.md index d966863..cb523fb 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,89 @@ -# geckiine +# SWAP DRC for TV-Only Wii U Games -This tool installs both TCPGecko and Cafiine into the system memory so that you can use them at the same time. +Introducing Swap DRC, a homebrew application that allows you to play TV-only Wii U games on your gamepad screen. -## Usage +Swap DRC works by switching display buffers between the TV screen and the gamepad screen with a press of a button activation. This app also includes the TCPGecko and Cafiine installers for the other mediums of modding. The gamepad sensor bar can also switch on when the TV display is switched to the gamepad screen, so playing with wiimotes with just the gamepad is very possible. -### Prerequisites -* Wii U (on firmware version 4.1.0 or higher) -* Homebrew Launcher -* a cafiine server (examples: [the original by Chadderz and MrRean](https://github.com/MrRean/Cafiine-410-551/blob/master/server/cafiine_server.exe), [MusicRandomizer](https://github.com/OatmealDome/SplatoonUtilities/blob/master/MusicRandomizer/README.md), [Ray's custom server](https://github.com/Syroot/CafiineServer), and more) -* Your computer's local IP ([Windows](https://support.microsoft.com/en-us/help/15291/windows-find-pc-ip-address), [macOS](http://osxdaily.com/2010/11/21/find-ip-address-mac/)) +Note that this mod has no audio swapping support, thus use headphones to listen to the audio from your gamepad if your game requires it. -### Instructions +## Instructions -Note: It is highly recommended that you set a static IP for your computer when using geckiine. For more information, click [here](https://github.com/OatmealDome/SplatoonUtilities/blob/master/Misc/StaticIPGuide.md). +To switch the TV and gamepad display buffers, press and hold the **L shoulder button**, then press **MINUS**. Switching them again will revert the displays back to normal. -0. Find your computer's local IP address. If you set a static IP because of the above recommendation, that static IP is your computer's local IP address.) -1. There are two possible ways to get a geckiine.elf file with your IP address. +If you're playing with Splatoon's enhanced swapping controls; - a. Go to [466gaming.ga/geckiine](http://466gaming.ga/geckiine) and enter in your IP address. Click the download button and extract the ZIP file. ++ Press **B** to switch screens except in-game menus. ++ Hold **A** + **D-PAD** in any direction to super jump to a teammate or the spawn point during a match. + +## Requirements + +* An SD card +* The Homebrew Launcher ([Haxchi](https://gbatemp.net/threads/haxchi-v2-0-a-persistent-wiiu-hack.451071/) or [Loadiine.ovh](http://loadiine.ovh) method) +* A Wii U (on firmware version 5.1.1, lower verions aren't tested) +* (Optional) A cafiine server (examples: [the original by Chadderz and MrRean](https://github.com/MrRean/Cafiine-410-551/blob/master/server/cafiine_server.exe), [MusicRandomizer](https://github.com/OatmealDome/SplatoonUtilities/blob/master/MusicRandomizer/README.md), [Ray's custom server](https://github.com/Syroot/CafiineServer), and more) +* (Optional) Your Wii U IP for TCPGecko or your computer's local IP for Cafiine ([Windows](http://www.nirsoft.net/utils/wnetwatcher.zip), [macOS](http://osxdaily.com/2010/11/21/find-ip-address-mac/)) +* For Splatoon's enhanced controls; ver 2.10.0 - 2.12.0 + + +## Tutorial + +### Video tutorial: + + (coming soon) + +### Text tutorial: + +1. Download the homebrew launcher from [here](https://github.com/dimok789/homebrew_launcher/releases) (download v1.3 if v2.1 crashes for you), and the swadrc.elf application from here (soonTM). + +2. Unzip both apps and then drag them into your SD Card, make sure both directories are at: + + * SD:/wiiu/apps/homebrew/app.elf + * SD:/wiiu/apps/swapdrc/swapdrc.elf + +3. Safely remove the SD card and insert it into your wii u, then launch the hombrew launcher from [loadiine.ovh](http://loadiine.ovh) in your Wii U browser. If you have the [haxchi](https://gbatemp.net/threads/haxchi-v2-0-a-persistent-wiiu-hack.451071/) homebrew launcher, that works too. + +4. Press **A** to install Swap DRC with TCPGecko, or press **B** to install Swap DRC with TCPGecko + Cafiine (cafiine server on your computer required) + +5. You're done! You now switch displays anywhere but not in the settings menu (because it terminates any mod installers like it always does). + +# FAQ + +### What's TCPGecko and Cafiine? + + TCPGecko is a mod that allows you to use a TCPGecko editor to modify the ram through a TCP connection. A + perfect example for this is the use of Splathax that let's you modify gears in your inventory in Splatoon. + + Caffine is another mod that lets you replace modified game files that you'd like the game to load. A perfect + example for this is the popular use of model and skin edits for Smash Bros for Wii U. Unlike the "Install + TCPGecko only" option, Caffine requires you to have a server running on your computer at all times. Don't + use this if you don't want to use game file mods and have the computer running all the time. + +### Can I get you banned playing online with Swap DRC in any game? + + Swapping displays doesn't modify the games directly but through the Cafe OS instead. Therefore it's 100% safe. + However you can still get banned with TCPGecko and/or Caffine mods if you don't use them properly. + +### r u a l33t hax0r? + + YeS I Am. + (...I'm joking this question isn't real) + + +# Credits + +### Creators: + ++ OatmealDome ++ Yahya14 + +### Special thanks: + ++ Maschell for HID to VPAD ++ Dimok for function_hooks and the pygecko server ++ Brienj for the IP selector and initial UI ++ /u/MachMatic for the banner background ++ BKOOL999 for feedback & testing the Swap DRC app - b. Download ```geckiine.zip``` with Geckiine Creator from [here](https://github.com/seresaa/geckiine-creator/releases/tag/v0.1) and extract it. Run ```Geckiine Creator.exe```, enter in your IP address into the four boxes, and click the "Create/Patch ELF" button. -3. Copy the ```geckiine``` folder to the ```wiiu/apps/``` folder on your SD card. -4. Insert your SD card into the Wii U and launch the Homebrew Launcher from [loadiine.ovh](http://loadiine.ovh). -5. Start a cafiine server on your computer. -6. Scroll to the "geckiine" application, tap on it, and tap the "Start" button. You will be returned to the Wii U menu. -7. Launch the game you want to modify. -8. Run any TCPGecko scripts and/or connect with TCPGecko dotNET/JGeckoU. -## Credits -* Maschell for HID to VPad -* Dimok for his amazing function_hooks system and pygecko server -* NWPlayer123 for the cafiine cient source code -* amiibu for helping me with the PHP script and giving me name ideas -* seresaa for putting together the banner, for name ideas, and for writing Geckiine Creator -* 466 for web hosting -* /u/MachMatic for creating the banner background -Shoutouts to everyone at the Splatoon Modding Hub Discord, because I probably annoyed them by talking endlessly about the various problems I encountered. diff --git a/src/main.h b/src/main.h index 62c5b1c..d7a5202 100644 --- a/src/main.h +++ b/src/main.h @@ -8,7 +8,6 @@ extern "C" { //! C wrapper for our C++ functions int Menu_Main(void); -void clearScreen(void); #ifdef __cplusplus } diff --git a/src/patcher/function_hooks.c b/src/patcher/function_hooks.c index 99238b7..03d1243 100644 --- a/src/patcher/function_hooks.c +++ b/src/patcher/function_hooks.c @@ -228,7 +228,6 @@ DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) if (buffer->btns_d & VPAD_BUTTON_MINUS && buffer->btns_h & VPAD_BUTTON_L) { drcMode = !drcMode; - log_printf("isSplatoon Address: %p\n", (void*)&isSplatoon); // enable/disable sensor bar VPADSetSensorBar(chan, drcMode); } From c477af73f82e7c190df7f5bf2874de280157b352 Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Mon, 17 Jul 2017 16:13:05 -0400 Subject: [PATCH 13/14] Menu + meta changes --- README.md | 6 ++-- meta/icon.png | Bin 30426 -> 6047 bytes meta/meta.xml | 21 +++++------ src/main.c | 94 +++++++++++++++++++++++--------------------------- 4 files changed, 58 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index cb523fb..3b94e4c 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ If you're playing with Splatoon's enhanced swapping controls; * An SD card * The Homebrew Launcher ([Haxchi](https://gbatemp.net/threads/haxchi-v2-0-a-persistent-wiiu-hack.451071/) or [Loadiine.ovh](http://loadiine.ovh) method) -* A Wii U (on firmware version 5.1.1, lower verions aren't tested) +* A Wii U (on firmware version 5.1.1, lower versions aren't tested) * (Optional) A cafiine server (examples: [the original by Chadderz and MrRean](https://github.com/MrRean/Cafiine-410-551/blob/master/server/cafiine_server.exe), [MusicRandomizer](https://github.com/OatmealDome/SplatoonUtilities/blob/master/MusicRandomizer/README.md), [Ray's custom server](https://github.com/Syroot/CafiineServer), and more) -* (Optional) Your Wii U IP for TCPGecko or your computer's local IP for Cafiine ([Windows](http://www.nirsoft.net/utils/wnetwatcher.zip), [macOS](http://osxdaily.com/2010/11/21/find-ip-address-mac/)) +* (Optional) Your Wii U's IP for TCPGecko or your computer's local IP for Cafiine ([Windows](http://www.nirsoft.net/utils/wnetwatcher.zip), [macOS](http://osxdaily.com/2010/11/21/find-ip-address-mac/)) * For Splatoon's enhanced controls; ver 2.10.0 - 2.12.0 @@ -42,7 +42,7 @@ If you're playing with Splatoon's enhanced swapping controls; 3. Safely remove the SD card and insert it into your wii u, then launch the hombrew launcher from [loadiine.ovh](http://loadiine.ovh) in your Wii U browser. If you have the [haxchi](https://gbatemp.net/threads/haxchi-v2-0-a-persistent-wiiu-hack.451071/) homebrew launcher, that works too. -4. Press **A** to install Swap DRC with TCPGecko, or press **B** to install Swap DRC with TCPGecko + Cafiine (cafiine server on your computer required) +4. Press **A** to install Swap DRC with TCPGecko, or press **B** to install Swap DRC with TCPGecko + Cafiine (cafiine server on your computer is required) 5. You're done! You now switch displays anywhere but not in the settings menu (because it terminates any mod installers like it always does). diff --git a/meta/icon.png b/meta/icon.png index 61b735e9c52dae2cefc56353d032ef8b2f21f9c0..0c5c82ae5def29334261782e29f8e5c1b388a178 100644 GIT binary patch literal 6047 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 R9Q3btsjjS}R1Jlp{s(LtL=6A{ literal 30426 zcmeIb1yo$iwy@g-f=eJk2yVfGySr;}Pmpfh9fCU{xCOW1uE9091@{2KA-MbNY+>i@ zv(J6p|Nig2@xKwqpqX83&RMIzs+u*cdW|ONm8=*NJT^Q406>xu7ghiOAiyF(2NoLq zdU#M62>t_SC9ZA@03ba5@e2V+NWuaD;N^^kgkHTevb3|bHL|oKln@dkw6d`@Fg61L z08TT>iiS#xo0vRjUylW)0zIRpEEO;dG}3 zLWYKVzQ>TKMtlc91+zkw5$cl}_^$VA>20RzM8nzIz-`qe?|R`;a>Wo#3oK%+IFme! zCt{u;KI)=R*XPcq6xmBFcL^2D2JnkQcqV@!Qv{?z0d)HG^_BszXaG9o9&4ij z&*by?w-5l$Xd(=Vv zpCFV2U=acI@_~Mo0I0VBoo*5mCxCA}0A2J@mHXgj@so8bFsb-*?pjg~5id;|j>2CBNZXuIJ+k`2 zMkGDFc6xesWo1h8v!JGKud3UvVcVM))f=-5ckb)6lf|ZQq+X2LUSd$^i*5bK(pk7e zk#N3xb8BH@*PjsXuJJ~RKTGJ z0w^`%g?Jl5ldG){c`8NzM9r?{+ZlLd)myfXQNTia8u=^@Io|E@-H4^V0C*ZmL|Ov? zuZ2lzm3k}qx?lkS;WRI*QURRfRxIikXx!GvbFB#1I;_5eq@UXap9sPOJ#lSxC=0y> zDf|aY@u+m@#`y7=TjY)WqpXl=+mvgNd8|+_bzxIlDH^=spai;MpXw6L1VZS&QzHq5 zeHQO`PSh$6g%(Uo*b|5@Pb?L|BF>=jPKi)i9Pg0F<`GALmS|lBS2uvs``W)jj3L^q zT%KnPu}Y{mmkrxjGy~xa(2gM?3^Oh9i%lgq&wJMN^)CfRC^KQaLS6JN8(1(*pUvoL zJKF`z*s0;7^!v()3lR%Cu}f77A?t%q^oPnEq0qcUTHsir90dt=@dd=yq}61n#B&L8 zNtsb+;Mm|GedXK8iKB9*D#_|lFFs@GF){?GiBpqIpoKl9d-66==rbEBT96PUd2RS3 ziL#GMBWNR{BNhrIo78!U%;MN2Q9Uz2({dP&XllZj-F_>{EA1;xD>y4ehnn!odi>TO z&lSH>DD;|0K3{#Z%Df5<`oJiloSC37pPR0P$`Ym_Sd?C^P$D0Y`;^%}fn&f2Q$i}M zC?jSR+vu6mnQ_U6T^;It48CmK7uAuzO|gx*4aj3hL?nLs{b4;GCEik5jjEc;6(gb-K1MQzECz>)PAM-xJO67wg7T4apHf)f zYelzWQDr8@`G_Z-SuJ+ojv(gg(lrmAzSR z=p;nYe_r84O=OBx;BW86@|mn`VA|Dzs{X?bUVSi6eqK6<5R)X6YK6j4v;iN?@(1hl zBs*ESb&8z0BlmY-(f267QQ~AXOV=`hv`q73<6_kc#0%sL#I_q*i+6I8vl~U~)vvse z1-c~3waCQ`!v-HGuPaU~&ga1AV9M}to)pvOn`Ysp*9$u~TjcD1NNIZQnIdhO^VPX= z{Sw!W?nddx{4(c63{efb0+AGY7I6@ZyMx8rk{ge%YxY21NV}b1C`&g+H*U!{qIQ@& zb6hk;6y?2fr`9s*vU#U@XC@gm84;P3%$Cet9-z(hPtA`inP z<9gzH;$-5&CmjtZ4eILL>Kc$l`HDui`fhcDg`Wn8dX}29hIWN$QF76XiTa}Y9Mqgz z*(lk9lnKN3(u3-r>by_SOIN3$XN#-NtKD=B^`04i>L_mCjcSZ?t8)vv;ekO4m_{zZ z)4+4Lt+YYsRN?%ZFqpK<=hkr?yGduLHuPj@ifOs}X&>ch<7CCeQ8B}3hPAdnM}fgX zQr>;EalEvNIGyv|jVqFNC)V0aE+Z$&i4}=$JGrwZyR5s$y8&~l{miM9De6qNU)sBc z7Ufrm`4CcL=uH<2-Q|SjybP<>N$B+HB2xy)wMkv(UFK%{%J^0N zO+Q=9r|wUEa_yEWZ~PX7JV@?>k5QdOJUIJd4kFL<#1@P`8a1mr{&W- z0`Jpm1uz7{yopP+M)rH(;h%P9JPL_RGP{qeY|UjOCXOlx2_J7kEOI zi~0V=;Zw&Kq43Uacx{Hnbi=H}fm1?SRQR%o;#4v&k>4X4Se!{an6ju>YkkS{!W*QK zq~{YkQ!o=82+bLJI2##!A|t}B1@nnyqN)wI4A%@C`U*jQ<+mLc!Jp{xV_8}D^$X)ZUn#z1!u3$$suGqbi%tgl3>ve0dcWV`d={ABg z{HmYZ_T1!-wwxNB`a+fNrGGLGFGkS2V)WT(aTp#`6mw3iI02Tu&GB>5m3al9Yk@-s zBL` z$6lFh7s;Ai?{qoHnu~`C? zBxY`PXUQX_9^;u!@6jm3!=d-dG0AT3v=?(avl-QI*YyV%Oi(QM>YmswjfmU@uX8nU z4Qd_M*d3P7u0B<*QB5e}d}F?4x5a%MH7eItpH!bvT&rbTyX(?e_155Q6DNgjaQ?W_ z`2h27VmyU|XTI^s#qzA<>|_CR-ra`$X0We*+L3&>s6npb%`yLuz_ieOz&M}g?cCJf zoQFw^W7^U1oY)z(pU=>3#7P*6(BrW9us(kz|LqiZUJj0Ld^R_m*EvE%z#+1fXSW%* zeZ|i(>D%?#BabjY4eXMe|)9N_qh_{!y zfFifzO6WmxXLM0^qWC4}D(ZPu)EyM$hoftKCYo6QKtRG+NzG18Mw(OK(wtToXsHLH zbuzaCC!zoVH=mQ0uD&VAj!+L|Xl%hlyjR~$OlS<`Ay#FPp_j1|0vQ>LyV!sfU1XK? zT}<^kfW&;f@Z3(EU(Srl}4YQm5q>%gO-7Xjg6U&nvjv6frXBqiH?b$hLMSrnVyrGk?@ZnVqSQ# z#BBpK;8YM6{i8bYJ04;qJ3A{*Iyy&3M_NZFT1y*4ItC674mx^9Iz~nsum+8-vxS|m z6ODx}$?s17^dk(i)weOWvNN`{ApGH1SI^Skj)$1|M@9EPf3(Zo>b@ci+dtTWDbhLV zTG27k($oEu5m5i$#>(Et?6+G3>eGSDK;|F|J6o_F!#~=Ak;=&2oBm^U=H~xsX=^9q z0B*q_ME=pzR>|24M5h3CL<@qaM;apiZj-^SGMUCj-q&M9OA(zUa+QL?l&0}1Qefq21|tTgm&H1rHgj0~LMvCRm6%gjkn z|C5v7HUH*A20V#?x^}w%>V;7WY|PBW$-wlpmw(ayyB|xSv4Qi0y!@s4lMkRir-7x7 zxvm|rvAM1xh|bEwkelwW!k;vM8@-$o7PfY}7WyCwVP0?nt+6qXQy&C0U||EY(9p9o z>e8@-m|1DqfqEP?20$iVR(fV8Rz`M~-*Cvt{A~Vju7xf2?SD)luFKhub1K^+&=Iz}4*#=m__5Y;a4>SvFdFC?&@eMH z)6;P1)9cXy4Om&24H%hqSwY~z{=eJ}e?*!;!_5D8eel;1);H3%Fa!a4>Hciip9TLX zb(=1S0gzo695EQ_S(s^9Il#eC&w!qp#(=|s9mveiqR+;_@Mrt}7iQ1DFA%?a?vKc4 zY2g5}`R~L&aD>$b=dvIhTV4YjOLIb9D=RZ&ecc~%l+M8d_(w8$zx)u|SrY!VM*hzI zCm;VWj#41V#`wPzUVgeu{Xa1g{vX!n|8YQlSeo)b4X8h*ZvQ`+nZGZP|C*}&ng0BH zYV#vG2IqLfzmHDQA9L!*`ucyL$$*m)@GgV%r+D~hZu!t~`Zx1`nTvmT2WOLirkDS{ zZ14A*`^o&Dyj%WHbIRXq`3EecTbNb%Y#hzSx(hzPMVaImt{Fw%mTtbf$|$}-YHMcyTk6WjNDuy@WBBpB1j| zzt7R1&OCk_6Tg>&PgKB%Idu1@IX?}T`<=l5e&Mec{qOgE@9|e9_b47B{KEARO7}Xy zaNVPLi0}*7Lnz(r{K9pQ;vvE>To0jiuk#DnJ&K12zi>T-(!I_vT=ys*BK*Sj5K8wt zzi{27c!=-|*Fz}X>-@rXkK!T1FI*3ybg%OZ*FB1d2)}SWgwnmvFI@L19wPk0^$<$; zI=^t;qj-q$3)e#^-Ru0qb&uj9!Y^D8p>(hF3)el0hX}uLJ%rM|&M#c|C>|pG!u1eJ z_d36D-J^Jj@C(;NDBbJ)!gY`0A;K?Q5219g^9$EKiiZfla6N?5z0NOO_b47B{KEAR zO7}XyaNVPLi0}*7Lnz(r{K9pQ;vvE>To0jiuk#DnJ&K12|0OQ?zrG&w@;`TzhIci_L90DwI`0I;P40C0W)0G?S!zUdGJ0H{hO zgawqGX1*uCbyXU#I&Z$}Ct-@`Hb6Th=4bTs=)eP>g5RP8z@j%L04zc& z0>C0%HUKO>y%lMNZ~N#CN0wCas0H^9tYq?=<|gEitI|j<;1_zg--_}eewf{rKT5-! zc`UF#;Fav>Gq=g7zLcCm7=h8N&__}*HjT%JnuV` z{ORS*XUF+#yFvsH+i>flu~+i58EPqP1HCYJ5nf%C2i-6^PDb|0Cbf50nReO8Hl-J@ zm=xD1a~E?aph=9YW~ehhPF@jMf7ad*Ux;#T1IWCO)%RT!Js|PtWs?*lS%pnLhlkXc z#Y*#Xz^05Q3=QGaj>vx%s$&ZBglVtfrEchK z2YgZ%=!J9N--2@uNoVX@pLVtqedqsiH1dO}!I9BSXkdE3S`z{!QviLqoN&+V=qc4| zh=1G{1|QLvaz}Do`A%iZTGFe zi_0WW1k@N82KPa8)x|(oG9SJ9A#>Y)ru|`nmAs$|(SXRhJf2K&P+H65I8}{qrUNJG}-)=?YIH(gr z!w!RUgT(IeBPP;uB@v^CmJC1x@_WJIL6jjcBFcBoPRiV~Ruv=TZxid2%SUXG`$cU~ zbF#sL@dK{v>V2boyN?K4scP(9BlDW#!!AB|K?Ul2O=q@5w#;aYwLe-cZ-x6v?tn7| zmlv)gu1MI8vwa4+SP5s4y7!)%DF=%b$3vruOKZ(OGl_IY`ixNha3Ncw)-om5VV)VIQ*P$-$(G^o=*0SLEJ_gTQ zB8R}Y6#Ji`r)$$mQ9b=fX}C+z6~$9?DMDgz=`n)QFYmlMW{o-35rS@rN9JFBU+i6y z1#DqMUSA~REe=2hkAD|v3&HDVF$M$Gl>PtF?SvaoAcv7_jdo3c0&^_!lF}$i_VRYIn_CQ>bj9-NL|TV zE+({bj%OYw_LeZ*LhOCD?a~d7qPVU9?VZ(`y!*M5u~GQx^SKxEm0qm)$@q+@z~^MQ zYXsk~dto+xxRAD9ad=z_boDn|?eN~-#E*ohS*>??>dWC8^H}RVZzb2LbxDdmuroR# z+X#Y3x9(K5^!*r7C!A!2R}eM5(d1vu92g8oZyOjAd?+N_l%Ob+-WukaB(JlhhKBy= zmVFfC_NFh6Pxt8Sa(MWoP00G_i=9^1P83*UWHC3H>no=1*jlzpn6P|^ias>-s< zh|`&QPd*&NOOUP#LD%V*9PnZ-hV}8G-n7Gi*NX0fA{Tg?rV#f<4o7>n3&#<0Wil92{_r`+x!`C1$uG7?j~yg0 zsY(C?$2`c<&pj+CGIYfy85LA20@HprKkKf+EIz!7k#aPoU;@oGJf2Y)8|@n zl9!U!eYUhbJbWlEYu=yj-1k@f>2;g=`g_Ce{MvaGt}1N0Gn1!x2aQhGZw~jXNaA^l`S9bCX|CkGABvFBQR=?=EjY!v?m0`TqLr3rc~i&CU&r zTmTtzl7*A!8Cr7G&fv+NmVtR^?2i$!bi{gD&EuluJ!n^J9>#Ef{h=R0Q{w=p|G*Jb z-18iRMF&l3&s#C(38F7q;&E$w5NV3@ARZF`bkjwL-@-MXV{?MeQr|M8oTUY*gE#)t z0NoYarM-dJyl%Q3O0f}bw88t49L0QWJLAhfpN3MF?%NsGlk-okBG;YNu%)Y|g}Qr= zV>|;d8LIeSMUu!zlI&L+&s~{6&dw~COWHsk8EDiYJ^?{nfNm$!@&Ow-XV?VczLNA2e)6sd=7C*+IE+!r+djCr0!w5 zWaVbII;Ta=V43~#ioqD7#69xy{Gzli!?J+w?@#Y2(kisc}7MK=wv+tvl=Y(>9Oa^<1KRJKtp zCOZP1BLm3>)-eqZCwZEmyiFoX&!p1oHH|+y*WAAt2|p_4 zGS3JBWmTNmuWlYQkL8k0a-DOT20O|`XMBC}<>+aq~yPys0Nn&dAg%2+}o}mWdWI65DlZk^l86!u=a1~4| zye`Pg>&K@`$7E{y#;N~)?s@Oou6ghQy~}&8K>6|Sw=}C&TBl#?SYyoToeqba#uUw& zapI>jNIhRF+VbQ0)jpjucUs-(IY0iiF}5&Yg@cNJ7WqVtv{YU2*=cS9fVSSRF{TefHl?nNm-*pudg(}W2uOjl$EccM~$~=`HC1RizhU-AqBNbwnil-Mx&F~hP z>^QRHUMkJ8ebreXOxC{DEC<5*`T5Pcoy||}7=DdkStClRkRzhny_=b~}qi9Zf;F@LiyPIBJ^^+%;j|ad_h~v?cENZTmYKp1P zuU*RvF}vN9!iYCLrEmQ1^3dYB$MFtb&H4#)Q}cxa-I05SyU~CWUH^hXVRH_jLT``1LE*#~ohtGD zgRds;mu;ddcVy+wjTSY_#H}zfHcsK1q@{shdfo~S!=#l|=)AU0-Pt20{bBP)Zi}SC2+RY4*BNe^tx- zP|`AAm69lCYRYJPTOJ~|Ks)*o#^ISL8zhfw-banSq-HaHsam?Rl!l(q9;5QEM_{8K zo|3(-NcY>VcdT{k(qx6c)Acm(>Vy&Fe8@(cXe1U&y2y3$C zRydVDvVbpc1B><)3c0?;0971w*aFJVt?m*~*A`hs&KyM8$0)~hg5H{TxR_s5v%?Ezo^I8y1HJF)oE=%lswCF!y~85s@?*>i1+-NWg#No*;mWLZx}X)INTG(coNmG znm_G;)T=5qMjaOiypJwhFCcY*_}5O<_)F4&4o4keynxz@cWzqU^N!7~5L|k(6>E4=Cp82)O za1p3&^*)k=sCsid8h)#uW>NG+%Pyujky@wjvOj7DZEKC5B!BY2pdK?q9o;%rNN#aS z$~XU%84SpXa8(Z39C8me={b&$rXPywnoc2y2ocvT^n~K-_x!o+_!2@XLVJY{gi+=# zC;IB!L0KaK9c8ohSMk&sj_{J0rW+I%NF{ejY;!GN(uI^q=bYD*0q^m75^isuite)_X{U&V%O@je72`BU@M>UYMzCoh(B3ECFTOv zO-yX9V&=(np-S}<&6LRRI&;SI;RZ-?9sM5h_@#kT14Ge_C- z@h`Q4kxz&cKVDVjO|%bElmTjMYv-)H@PLMf`ek<7vu?Y!>sFjxy9iF}$&OCng2=Hr zY)BpF?VpA5oT`<;dFIcM$&OzMnM)7^QY0at0`WCYAHTt~eAUkc@_dg?!~C40h@T}@ z{AFO9tM=&I?~N7KL|RQulA7F)XLg32^d^vtDKmiL%{60BrSNmK!y_rW#W7Yu@ct|C z?+&YujtN}wjeESugas7zx+khMC z_EIs2TeYdJSxYcgt1v)P%$A08Y|B?J_`qZ+%RZlacWnq%Cu3oW$w_f}2ML30b#pSg zZ8215zukr{WN&ZpE5sluA!$z-&NZViC5%mv4^*qy&!o_^YzneO)3{D>Y=-4X8#&Vqm?^8;x>vO2YnjKN=?<#l$J$D zO#+mof!#Id>SoAou_?T8jy^e?m$Ej0?-b3jK7@jTg1Cf)?w2%y!q<)1!5xCe#+1vQ zA?-_6^yV|n6NT#S&)&ESNJ_%vhjqPjZ8;j^8=9-NJ-BdvN%(j)CRRr zhu-H1P%flDJ&9hSA}KX~V|H`n9D~yOWPWq}vFFQ>W=lSPd5={Dg4a$;4ts(%%_hxt9*h$k!SiT z5-dO>B+ggZ+^0Oh(Rx`F-+2YqVejj}&DnySjSXW*M@P-Pg)8qHr?uS%J$n64#CPxB zb@%swY-&oGm{5U6!UngSqK{M*TYkTV=6u z>}Io*LLXFtD{r2A*w!o1TgvU9uJ{^x( z5!k;kO2YC~Q&c!_Jx>@|&Vn%GU0jas>Ai8A1+~|%hsbnpm(CzA8IIRQr8iO9l;UyP z1rBG5Rk&R_NJ>iPmXxg5u7i*5&TO}$%SWxcLh-&&mH8+as1P}7YKV)A6VlLxY>wtI zxnDaO45fs0jg}2wx55yVdfd5#(VU-@cnp+-`kWTMU~0CgRzZ>eYbv*8Zv@$+XIY#B zyGnr`rn7MFCwM37x6{uV`8-NY*M_I}3lKm;Ol{Sf<@x#Cre?GrP0rkRRmc3kI+(+* z=sQkiJU_@STfNQGJ_y^6B)#=sO!@*wFP_dzf5PlVR-unjUj$fL)4T z9f9Wlt~)~cTx;%+KAdd6WqI-91=J&mPy)U|@5cza`T5`G9Tz$bDk74S3hSPWtEj1R zyInE|pb)HO#l6-W&Jbz1SWA?SXY_k>{q32S>p_Rvd|ixsg@L@1(&rBh`c|CDu6u76 z6wO~{%(wNVAxKaV_^5?vnL(0s6~0^AVcg%0Q0XNrYDK;_|JZKF?)&3P<544HW8IA}=^wMQtQXwQ%8Z7I*M?H% z%*|=YopJ1sya3=7g7>9r@k)9CenvV`CGc#kpv3F>UU6 zU*I#n79A5u+;6op^-deu_8MO~wbtSY;I@#;zp%+bidz|$A4h?E@)6zoiSq6qDUS4B zPDyh`vQ_0UmaIY!s4Z|^sp50MTh8joh9Ho2I}+O~1%~ph64Rki(_60SVHkb>^$Ds4U7E9GLH8a z_-K8A;8-zd(??@AR}(QYv9X;kCdW!#cxn;i`Sn9jM_eTr*WS|#sS1z5@&i6cDDIMEf`@X>(A&cGc(AlSJRl^G9lxTau5zYR=4Qh zh7_WuFyJRpYpnM+O;vA?l<8znOahuhm0%egnz*Ba0^F|U@>uci7GUFnZzmf>Hz_wi z#DuI3k0gYwN%bB?hOcxkpf8^KZ95Goup@n|-K^C7S^6t6E$z^7&-BN%*& zfn~eapPruX#kSxYh4E5l|9Di+_U`7aV8VH7@^c*|joPKe6pfV|>UEdVj?6O}f%tk% z^R7r0tkc++>YA92v~7D?C&C?(Bjalqac2uy2`zC=GBH`p zq%+OsTrym4GWiJ6@xFfu3GdNxH68cyW_Bwt_Ck~SIrh!<(!6>9n~Er@fK{8O_rO%ne!vEMlYTJ7F)2w7` z3KfC9%z)X~H$uuqsRLI9Wk?jA)8wkE$x95Ww=n9X^*TJ|F-2#HStVV@HLXQOMQYTT ztY%X!UXU=k1qJ$(#o9n1@RgdHxV1F{_}l>X0^j4>dbjDyLPJA?-D#gNjQbE40h5|P z7Q}nKFEpO)3uAKKaGIC8_a ziRCV@K>)b9CTT&t^K3U{Fmi_2OW1Rwgw?wlyZ&+EMCfX1DKN*}S=uh?a6~;VXXRPM zoSd7_yE}1?94ZGiGX?`_@PsR;-KZleDnF(fKdy};jx&Qi;mzmME>f3E&5%G{suJDi zh;nv`q?=)jxgh%T` zhMOZvzHL(9N|tx{9KcpU;84&eFN3D$ zimQ&Dopc;e9y~DA$&LexJV|V2G)lum8VC>rnz;D zK!FWX_WQK>>0_pFP7!REQHML>>R>e{qnYRC2oqus_U z+U9E;huyiJ`n{$;OZOw3LKV|6tEtK}cE`p#JPEWZTd@p`Cn7mWxXmdP6`9$Aj%QAA zDHLMNm*F?#YBb^D8*Q6Cr1fw3+; z~wIA6ueq43QE6Mv%6hIHs2p| zKdsn5Q+@61_x?R1KvGJ|`C>H=yyY7k8?%}Q#aS3X;@9pBDDA9+Lg&*ivAP+NNNAiwysF$<=rhdsJ7blsMmw|Xa|4LLa zf3jhF%r{(dY~qMZ@~Qcveh+Vnfn{OK*I6*FL)%*^}4d5_5sE(W3F6vNISwFJMZ z4Z+v1HWU_*T6P>p$HqQedR)yGJIH9(>_w1>ePA|Lh$HD>GoL}n#733POY1MI6J=BY zpEl9{fNjuM8Dh4Q??gWU<$t_UxWXX=Vc$uRbzEw^FCoquL3A_HpvtyUAs1(ak!$G>HgyP70 zHJmgOuM@F)Rr95j?zrq$!Xq_v*0~#)#END()awiTX#D~4&=m359o(q}No~az`Xfh} zoY5Ze%x^QjQdd`(PUfr%R&72~_x`cjs2Ji!NQ9LfZ1(BeHim=dc%9QAHoj)H)Z0r^ zyVpW1B`KzerA)6*q2o@D`G7G?KV$qQ}@_78t=4byXTS8kgz>%!6bSmja zhTW7IaInl$PTPJumd;q*k8s%Dvwng#oXq8DGb+PY=6qx@XTkPq&ISQ|II-M@Ku3y& zNGyS-tgOs^^}V7$m5;#lV7aS8w;j6UaM#@)auzu`W7Up?Fd$YOmzLTACTP>mx`yeS z;9~E<-lj&Xa`Yf3&ZbYW#P=vun+7;-LM{g0Rb1mh0l?h37cYd><(T!#J2^GG*<*YX zsy@c7tSoA^Qcv)VcyYZ@s@o0=?Gqgn<41>ErbeyxcBhJ3tL9Z%q5mjEvHPVPqm;oD zGh=A=&d9~@F`=B!rSGF)n(1*l;*yp-mT9&kPIcRwX@MO<+94K?{Wk)#9dcJGH(iw% z`pK_CZCYCj@rkH>bq-g0&@nM>23RKdzXj8kJM3tL;&P0D+K0f~vYNZwt9S-|e-rf* z*BThJAT?6B;Q8SKywy!UEV;YZ^DyO+k&T>TRT-(M)Y#5$!Vq5|$|)&Z@q72R7B&G* zu50W*RJNiR`x5hUmG5MYoAgH(DcGuy#>U6xH8q2W)-%C}ApQN)Hnz4sgA)!D7jiHk zPR?x@-;pgI1LKo`-gywmvCx3NHCA+a&_ES%$`8#4PYhE@IoZI(;{w~* zu)S?I3jI^~3ve@07ANe>m(C~hceafV$6a@PrH+uhcyt1L1jt-7!O<>=XLjx#-;?dv zfQ>r7vLj23?&qxjLYfnmMfHxoBwhQBw%YS&^d^gXa?+in9|gA z-fCAZ7_E$EJf?EOaW3(T3KT?WybzAArWzL95HAVH_TIR99dc}2X_vdNQpwsw)jWG^ zipcMcUI$4;wMTI*LI^8UG|vo3_lXm6B=D4F`E24C&T{++dGC6|G~$DUA)1?*tY{>4 zuMsiXUw>E}%|x}oFWo>V+IgUFo^*B2f+Sv&NOIDA_`!_!Li^%xa< zP1AB%gJwn0^0{Pov@7&^ZjM`e96?4*0Y;nmV1tX*q@=z~nSj2OkqiTIri#=!;)*N_ zJkMN4+$H=Nnu%x(uE+@*=lhFYb5!ir{KqGDU7u#}1kFi}HiNOf=mdBDqe6M#X{e%) zv*@X7k+ewV9)HSEABXeM1p-B*C?rq1=O@0{LtVgPe0@*BhK( - geckiine - multiple people - https://github.com/xhp-creations/Geckiine - 1.1 - 201607080000000 - TCPGecko and Cafiine combined - This tool installs both TCPGecko and Cafiine into system memory so that you can use them at the same time. + Swap DRC + OatmealDome and Yahya14 + TBA + 1.0 + 201707190000000 + Switch TV display onto the gamepad + This tool installs Swap DRC, TCPGecko, and/or Cafiine into system memory. + +Switch the TV and gamepad display (and the DRC sensor bar) by holding the L shoulder button, and then press MINUS. - Special thanks to: Maschell, dimok, NWPlayer123, amibu, seresaa, /u/MachMatic, and brienj! - - OatmealDome says, "Shoutouts to everyone at the Splatoon Modding Hub Discord, because I probably annoyed them by talking endlessly about the various problems I encountered." + Special thanks to: Maschell, dimok, NWPlayer123, Brienj, and BKOOL999! + diff --git a/src/main.c b/src/main.c index d36736a..284b350 100644 --- a/src/main.c +++ b/src/main.c @@ -23,6 +23,8 @@ #define PRINT_TEXT2(x, y, ...) { snprintf(msg, 80, __VA_ARGS__); OSScreenPutFontEx(0, x, y, msg); OSScreenPutFontEx(1, x, y, msg); } #define PRINT_TEXT3(x, y, _fmt, ...) { __os_snprintf(msg, 80, _fmt, __VA_ARGS__); OSScreenPutFontEx(1, x, y, msg); } +#define BUILD 1.0 + /* IP union */ typedef union u_serv_ip @@ -31,7 +33,7 @@ typedef union u_serv_ip uint32_t full; } u_serv_ip; -void gambitScreen() +void gambitBootScreen() { memoryInitialize(); // Init screen and screen buffers @@ -47,33 +49,31 @@ void gambitScreen() OSScreenEnableEx(0, 1); OSScreenEnableEx(1, 1); - //OSScreenClearBufferEx(1, 0); - //OSScreenClearBufferEx(0, 0); PRINT_TEXT2(0, 1, "Splatoon detected! Enhancing swap controls..."); - PRINT_TEXT2(2, 3, "Tips:"); - PRINT_TEXT2(2, 5, "Press B to switch screens except in-game menus."); - PRINT_TEXT2(2, 6, "Hold A + D-PAD to super jump to a teammate in a match."); - - PRINT_TEXT2(10, 9, " Teammate 2"); - PRINT_TEXT2(10,10, " _ "); - PRINT_TEXT2(10,11, " _| |_"); - PRINT_TEXT2(10,12, "Teammate 1 |_ _| Teammate 3"); - PRINT_TEXT2(10,13, " |_|"); - PRINT_TEXT2(10,16, " Spawn Point"); - - PRINT_TEXT2(50, 8, " ____________"); - PRINT_TEXT2(50, 9, "| Teammate 1 |"); + PRINT_TEXT2(2, 4, "Tips:"); + PRINT_TEXT2(2, 6, "Press B to swap displays except in-game menus."); + PRINT_TEXT2(2, 7, "Hold A + D-PAD to super jump to a teammate in a match."); + + PRINT_TEXT2(10, 10, " Teammate 2"); + PRINT_TEXT2(10, 11, " _ "); + PRINT_TEXT2(10, 12, " _| |_"); + PRINT_TEXT2(10, 13, "Teammate 1 |_ _| Teammate 3"); + PRINT_TEXT2(10, 14, " |_|"); + PRINT_TEXT2(10, 16, " Spawn Point"); + PRINT_TEXT2(50, 9, " ____________"); + PRINT_TEXT2(50, 10, "| Teammate 1 |"); PRINT_TEXT2(50, 10, " ____________"); - PRINT_TEXT2(50, 11, "| Teammate 2 |"); PRINT_TEXT2(50, 11, " ____________"); + PRINT_TEXT2(50, 12, "| Teammate 2 |"); PRINT_TEXT2(50, 12, " ____________"); - PRINT_TEXT2(50, 13, "| Teammate 3 |"); PRINT_TEXT2(50, 13, " ____________"); - PRINT_TEXT2(50, 14, " _______"); - PRINT_TEXT2(50, 15, "| Spawn |"); - PRINT_TEXT2(50, 16, "| Point |"); - PRINT_TEXT2(50, 16, " _______"); + PRINT_TEXT2(50, 14, "| Teammate 3 |"); + PRINT_TEXT2(50, 14, " ____________"); + PRINT_TEXT2(55, 15, " _______"); + PRINT_TEXT2(55, 16, "| Spawn |"); + PRINT_TEXT2(55, 17, "| Point |"); + PRINT_TEXT2(55, 17, " _______"); OSScreenFlipBuffersEx(1); @@ -130,16 +130,13 @@ int Menu_Main() if (strcasecmp("Gambit.rpx", cosAppXmlInfoStruct.rpx_name) == 0) { log_printf("Splatoon enhanced swapping enabled.\n"); - gambitScreen(); + gambitBootScreen(); isSplatoon = 1; } - else + else if (isSplatoon == 1 && strcasecmp("miiverse_post.rpx", cosAppXmlInfoStruct.rpx_name) != 0) { - if (isSplatoon == 1 && strcasecmp("miiverse_post.rpx", cosAppXmlInfoStruct.rpx_name) != 0) - { - log_printf("Splatoon enhanced swapping disabled.\n"); - isSplatoon = 0; - } + log_printf("Splatoon enhanced swapping disabled.\n"); + isSplatoon = 0; } log_printf("Starting the TCPGecko server.\n"); @@ -186,17 +183,17 @@ int Menu_Main() VPADRead(0, &vpad_data, 1, &error); // Title - PRINT_TEXT2(20, 1, "-- Swap DRC --"); + PRINT_TEXT2(20, 1, "-- Swap DRC v%.1f --", BUILD); if (gui_mode == 0) // IP selector { PRINT_TEXT2(0, 4, " IP : %3d.%3d.%3d.%3d", ip.digit[0], ip.digit[1], ip.digit[2], ip.digit[3]); - PRINT_TEXT2(0, 6, "Use the D-Pad to enter in your computer's IP address,"); + PRINT_TEXT2(0, 6, "Use the D-Pad to enter in your computer's IP address for Cafiine."); PRINT_TEXT2(0, 8, "Press A to install with TCPGecko."); - PRINT_TEXT2(0, 9, "Press Y to install with TCPGecko + Cafiine. (need server running)"); - PRINT_TEXT2(0, 10, "Press B to view guide."); - PRINT_TEXT2(0, 11, "Press X for credits."); - PRINT_TEXT2(0, 13, "Press Home to Exit."); + PRINT_TEXT2(0, 9, "Press Y to install with TCPGecko + Cafiine. (needs server running)"); + PRINT_TEXT2(0, 11, "Press B to view guide."); + PRINT_TEXT2(0, 12, "Press X for credits."); + PRINT_TEXT2(0, 15, "Press Home to exit."); PRINT_TEXT2(8 + 4 * sel_ip, 3, "vvv"); @@ -204,15 +201,15 @@ int Menu_Main() } else if (gui_mode == 1) // Credits { - PRINT_TEXT2(0, 5, "* Maschell for HID to VPAD"); - PRINT_TEXT2(0, 6, "* Dimok for function_hooks and the pygecko server"); - PRINT_TEXT2(0, 7, "* brienj for the IP selector and initial UI"); - PRINT_TEXT2(0, 8, "* amiibu for help with the PHP downloader script"); - PRINT_TEXT2(0, 9, "* seresaa for the banner and Geckiine Creator"); - PRINT_TEXT2(0, 10, "* 466 for web hosting"); - PRINT_TEXT2(0, 11, "* /u/MachMatic for the banner background"); - PRINT_TEXT2(0, 13, "* OatmealDome and Yahya14 for Swap DRC"); - PRINT_TEXT2(0, 14, "Press X to return to the IP selector."); + PRINT_TEXT2(0, 3, "Creators:"); + PRINT_TEXT2(2, 5, "* Oatmealdome and Yahya14"); + PRINT_TEXT2(0, 7, "Special Thanks:"); + PRINT_TEXT2(2, 9, "* Maschell for HID to VPAD"); + PRINT_TEXT2(2, 10, "* Dimok for function_hooks and the pygecko server"); + PRINT_TEXT2(2, 11, "* brienj for the IP selector and initial UI"); + PRINT_TEXT2(2, 12, "* /u/MachMatic for the banner background"); + PRINT_TEXT2(2, 13, "* BKOOL999 for testing the Swap DRC app"); + PRINT_TEXT2(0, 15, "Press B to return to the menu."); } else if (gui_mode == 2) // Guide @@ -232,11 +229,11 @@ int Menu_Main() PRINT_TEXT2(0, 1, " |||"); PRINT_TEXT2(0, 2, " vvv"); - PRINT_TEXT2(0,10, " <---"); + PRINT_TEXT2(0,10, " <---"); - PRINT_TEXT2(0,13, "Hold L then press Minus to swap screens."); - PRINT_TEXT2(0, 15, "Press B to return to the IP selector."); + PRINT_TEXT2(0,13, "Hold L then press Minus to swap displays."); + PRINT_TEXT2(0, 15, "Press B to return to the menu."); } @@ -366,6 +363,3 @@ int Menu_Main() return EXIT_RELAUNCH_ON_LOAD; } - - - From f140c6e60fbcfdc7410899b6bc09cb435c37f1e5 Mon Sep 17 00:00:00 2001 From: Yahya14 Date: Mon, 17 Jul 2017 18:07:31 -0400 Subject: [PATCH 14/14] Fixed splatoon's in-game menu bug --- src/patcher/gambit_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patcher/gambit_functions.c b/src/patcher/gambit_functions.c index 6a7c2f4..abece13 100644 --- a/src/patcher/gambit_functions.c +++ b/src/patcher/gambit_functions.c @@ -15,7 +15,7 @@ void gambitDRC() { if (*inkstrikeEq == 2 && *spTimer != 0) swapForce = 1; - else if (AButton) + else if (AButton && *ptr2 > 0x1C000000) swapForce = 1; else swapForce = 0;