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..3b94e4c 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 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'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
+
+
+## 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 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).
+
+# 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/meta/icon.png b/meta/icon.png
index 61b735e..0c5c82a 100644
Binary files a/meta/icon.png and b/meta/icon.png differ
diff --git a/meta/meta.xml b/meta/meta.xml
index 0fda6a2..de32a69 100644
--- a/meta/meta.xml
+++ b/meta/meta.xml
@@ -1,14 +1,15 @@
- 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/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/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/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 6a5fe86..284b350 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,11 @@
#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); }
+
+#define BUILD 1.0
+
/* IP union */
typedef union u_serv_ip
@@ -28,7 +33,56 @@ typedef union u_serv_ip
uint32_t full;
} u_serv_ip;
-static unsigned int patched = 0;
+void gambitBootScreen()
+{
+ 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);
+
+ PRINT_TEXT2(0, 1, "Splatoon detected! Enhancing swap controls...");
+ 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, " ____________");
+ PRINT_TEXT2(50, 12, "| Teammate 2 |");
+ PRINT_TEXT2(50, 12, " ____________");
+ PRINT_TEXT2(50, 13, " ____________");
+ 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);
+
+ sleep(1);
+ MEM1_free(screenBuffer);
+ screenBuffer = NULL;
+
+ memoryRelease();
+}
/* Entry point */
int Menu_Main()
@@ -62,100 +116,144 @@ 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)
+
+ // Check for Splatoon (Gambit)
+ if (strcasecmp("Gambit.rpx", cosAppXmlInfoStruct.rpx_name) == 0)
{
- log_printf("Returning to the Wii U menu.\n");
-
- SYSLaunchMenu();
-
- log_deinit();
- return EXIT_RELAUNCH_ON_LOAD;
+ log_printf("Splatoon enhanced swapping enabled.\n");
+ gambitBootScreen();
+ isSplatoon = 1;
+ }
+ else if (isSplatoon == 1 && strcasecmp("miiverse_post.rpx", cosAppXmlInfoStruct.rpx_name) != 0)
+ {
+ log_printf("Splatoon enhanced swapping disabled.\n");
+ isSplatoon = 0;
}
- // Check for Splatoon (Gambit)
- 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) | (2<<8) | (15<<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(20, 1, "-- Swap DRC v%.1f --", BUILD);
+
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 for Cafiine.");
+ PRINT_TEXT2(0, 8, "Press A to install with TCPGecko.");
+ 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");
}
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, 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
+ {
+ 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 displays.");
+ PRINT_TEXT2(0, 15, "Press B to return to the menu.");
+
+
}
-
+
if ((vpad_data.btns_h & VPAD_BUTTON_A) && gui_mode == 0)
{
// Set wait message
OSScreenClearBufferEx(1, 0);
- PRINT_TEXT1(43, 17, "Installing geckiine...");
+ OSScreenClearBufferEx(0, 0);
+ PRINT_TEXT2(42, 17, "Installing TCPGecko...");
+ ip.full = 0;
+ OSScreenFlipBuffersEx(1);
+ break;
+ }
+ else if ((vpad_data.btns_h & VPAD_BUTTON_Y) && gui_mode == 0)
+ {
+ // Set wait message
+ OSScreenClearBufferEx(1, 0);
+ OSScreenClearBufferEx(0, 0);
+ PRINT_TEXT2(42, 17, "Installing geckiine...");
OSScreenFlipBuffersEx(1);
break;
}
@@ -168,6 +266,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 +283,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 +293,31 @@ int Menu_Main()
{
sel_ip++;
sel_ip = sel_ip % 4;
- delay = 12;
+ delay = 8;
}
}
- else if ((vpad_data.btns_h & VPAD_BUTTON_UP) && gui_mode == 0)
+ 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 = 12;
+ delay = 10;
+ }
+ }
+ 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 = 2;
+ }
+ }
+ 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,46 +325,41 @@ int Menu_Main()
if (--delay <= 0)
{
ip.digit[sel_ip]--;
- delay = 12;
+ delay = 2;
}
}
+ 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)
+ {
+ RestoreInstructions();
+ return EXIT_SUCCESS;
+ }
+
+ SYSLaunchMenu();
+
patched = 1;
new_addr = ip.full;
- }
-
- log_printf("Returning to application.\n");
- log_deinit();
-
- 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);
+ log_printf("Returning to application.\n");
+ log_printf("De-initializing logging.\n");
+ log_deinit();
}
-}
-
+ return EXIT_RELAUNCH_ON_LOAD;
+}
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 2f4a8b9..03d1243 100644
--- a/src/patcher/function_hooks.c
+++ b/src/patcher/function_hooks.c
@@ -14,6 +14,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
@@ -25,6 +26,8 @@
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \
res my_ ## name(__VA_ARGS__)
+int swapForce = 0;
+
DECL(int, FSAInit, void) {
if ((int)bss_ptr == 0x0a000000) {
memset_bss();
@@ -184,6 +187,11 @@ DECL(int, FSIsEof, void *pClient, void *pCmd, int fd, int error) {
return real_FSIsEof(pClient, pCmd, fd, error);
}
+DECL(void, VPADSetSensorBar, s32 chan, bool on) {
+ real_VPADSetSensorBar(chan, on);
+}
+
+
DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan_target)
{
// GX2 destinations:
@@ -194,137 +202,55 @@ DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan
// 0x0 = normal
// 0x1 = swap
- if (drcMode == 1)
- {
- if (scan_target == 0x1)
- {
- real_GX2CopyColorBufferToScanBuffer(colorBuffer, 0x4);
- }
- else if (scan_target == 0x4)
- {
- real_GX2CopyColorBufferToScanBuffer(colorBuffer, 0x1);
- }
- }
+ // check drc swap and force the drcMode to default when inkstrike is activated
+ if (drcMode == 0 || swapForce)
+ {
+ real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target);
+ }
else
{
- real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target);
+ 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)
- {
- 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;
- }
- }
- 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;
- }
- }
+ // switch on L and SELECT
+ if (buffer->btns_d & VPAD_BUTTON_MINUS && buffer->btns_h & VPAD_BUTTON_L)
+ {
+ drcMode = !drcMode;
+ // enable/disable sensor bar
+ VPADSetSensorBar(chan, drcMode);
+ }
- // disable touchscreen input if the TV is on the DRC
- if (drcMode == 1)
- {
- buffer->tpdata.touched = 0;
- buffer->tpdata1.touched = 0;
- buffer->tpdata2.touched = 0;
- }
+ // patches splatoon enhanced controls
+ if (isSplatoon)
+ {
+ gambitPatches(buffer);
+ gambitDRC();
+ }
- return ret;
+ return real_VPADRead(chan, buffer, buffer_size, error);
}
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;
- }
- }
- }
-}
-
-DECL(void, VPADGetTPCalibratedPointEx, int chan, int resolution, VPADTPData *screen, VPADTPData *raw)
-{
- real_VPADGetTPCalibratedPointEx(chan, resolution, 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;
- }
- }
- }
+ if (isSplatoon)
+ {
+ // handles modified touch input for super jumps
+ gambitTouch(screen);
+ }
}
/* *****************************************************************************
@@ -358,10 +284,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(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(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)
};
diff --git a/src/patcher/function_hooks.h b/src/patcher/function_hooks.h
index 8b8539b..f5061c2 100644
--- a/src/patcher/function_hooks.h
+++ b/src/patcher/function_hooks.h
@@ -14,6 +14,7 @@ struct fs_async_t {
void *queue;
};
+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
new file mode 100644
index 0000000..abece13
--- /dev/null
+++ b/src/patcher/gambit_functions.c
@@ -0,0 +1,139 @@
+#include
+#include
+#include "dynamic_libs/vpad_functions.h"
+#include "retain_vars.h"
+#include "utils/logger.h"
+#include "gambit_functions.h"
+#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 && *ptr2 > 0x1C000000)
+ swapForce = 1;
+ else
+ swapForce = 0;
+}
+
+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 gambitPatches(VPADData *buffer)
+{
+ // prevents the game from crashing
+ if (*ptr < 0x1C000000)
+ {
+ inkstrikeEq = (uint32_t*)0x10000000;
+ spTimer = (uint32_t*)0x10000000;
+ }
+ 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
+ if (buffer->btns_d & VPAD_BUTTON_B)
+ {
+ drcMode = !drcMode;
+
+ // enable/disable sensor bar
+ VPADSetSensorBar(0, drcMode);
+ }
+
+ // 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;
+ }
+ }
+ }
+}
diff --git a/src/patcher/gambit_functions.h b/src/patcher/gambit_functions.h
new file mode 100644
index 0000000..5b5d1c2
--- /dev/null
+++ b/src/patcher/gambit_functions.h
@@ -0,0 +1,28 @@
+#ifndef _GAMBIT_FUNCTIONS_H_
+#define _GAMBIT_FUNCTIONS_H_
+
+#include "dynamic_libs/vpad_functions.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ 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
+}
+#endif
+
+#endif /* _GAMBIT_FUNCTIONS_H_ */
diff --git a/src/retain_vars.c b/src/retain_vars.c
index 4b76f1a..52dbb6e 100644
--- a/src/retain_vars.c
+++ b/src/retain_vars.c
@@ -2,5 +2,13 @@
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
+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;
+
+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 4c22123..4b14079 100644
--- a/src/retain_vars.h
+++ b/src/retain_vars.h
@@ -5,7 +5,14 @@
extern int isSplatoon;
extern int drcMode;
-extern int screenPressTimeout;
+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