From 19034d1639d599ab301a6c1956db2655590d38bc Mon Sep 17 00:00:00 2001 From: Maschell Date: Sat, 24 Sep 2022 22:57:24 +0200 Subject: [PATCH] Add support for Classic Controller, Pro Controller and Wiimote --- README.md | 2 +- src/function_patcher.cpp | 53 +++++- src/utils/WUPSConfigItemButtonCombo.cpp | 17 ++ src/utils/input.cpp | 217 ++++++++++++++++++++++++ src/utils/input.h | 13 ++ 5 files changed, 292 insertions(+), 10 deletions(-) create mode 100644 src/utils/input.cpp create mode 100644 src/utils/input.h diff --git a/README.md b/README.md index 6ae1e71..4025334 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The screenshots will be saved on the SD card in the folder `sd:/wiiu/screenshots 3. Requires the [MemoryMappingModule](https://github.com/wiiu-env/MemoryMappingModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`. ## Usage -Press a button combo (default is L + R + ZL + ZR) on the GamePad to take a screenshot. +Press a button combo (default is L + R + ZL + ZR) on the GamePad, Pro Controller or Classic Controller to take a screenshot. Via the plugin config menu (press L, DPAD Down and Minus on the GamePad, Pro Controller or Classic Controller) you can configure the plugin. The available options are the following: - **Settings**: diff --git a/src/function_patcher.cpp b/src/function_patcher.cpp index ddd8107..1e71c08 100644 --- a/src/function_patcher.cpp +++ b/src/function_patcher.cpp @@ -2,17 +2,17 @@ #include "fs/FSUtils.h" #include "retain_vars.hpp" #include "screenshot_utils.h" -#include "utils/StringTools.h" +#include "utils/input.h" #include "utils/logger.h" #include -#include #include +#include #include #include -static bool takeScreenshotTV = false; -static bool takeScreenshotDRC = false; -static uint8_t screenshotCoolDown = 0; +static bool takeScreenshotTV = false; +static bool takeScreenshotDRC = false; +static uint8_t screenshotCoolDown = 0; DECL_FUNCTION(int32_t, VPADRead, VPADChan chan, VPADStatus *buffer, uint32_t buffer_size, VPADReadError *error) { VPADReadError real_error; @@ -24,9 +24,6 @@ DECL_FUNCTION(int32_t, VPADRead, VPADChan chan, VPADStatus *buffer, uint32_t buf takeScreenshotDRC = gImageSource == IMAGE_SOURCE_TV_AND_DRC || gImageSource == IMAGE_SOURCE_DRC; screenshotCoolDown = 60; } - if (screenshotCoolDown > 0) { - screenshotCoolDown--; - } } if (error) { @@ -35,7 +32,42 @@ DECL_FUNCTION(int32_t, VPADRead, VPADChan chan, VPADStatus *buffer, uint32_t buf return result; } +DECL_FUNCTION(void, WPADRead, WPADChan chan, WPADStatusProController *data) { + real_WPADRead(chan, data); + + if (gEnabled && screenshotCoolDown == 0 && OSIsHomeButtonMenuEnabled()) { + if (data[0].err == 0) { + if (data[0].extensionType != 0xFF) { + bool takeScreenshot = false; + if (data[0].extensionType == WPAD_EXT_CORE || data[0].extensionType == WPAD_EXT_NUNCHUK) { + auto buttonCombo = remapVPADtoWiimote(gButtonCombo); + // button data is in the first 2 bytes for wiimotes + if (((uint16_t *) data)[0] == buttonCombo) { + takeScreenshot = true; + } + } else if (data[0].extensionType == WPAD_EXT_CLASSIC) { + auto buttonCombo = remapVPADtoClassic(gButtonCombo); + if ((((uint32_t *) data)[10] & 0xFFFF) == buttonCombo) { + takeScreenshot = true; + } + } else if (data[0].extensionType == WPAD_EXT_PRO_CONTROLLER) { + auto buttonCombo = remapVPADtoClassic(gButtonCombo); + if (data[0].buttons == buttonCombo) { + takeScreenshot = true; + } + } + if (takeScreenshot) { + takeScreenshotTV = gImageSource == IMAGE_SOURCE_TV_AND_DRC || gImageSource == IMAGE_SOURCE_TV; + takeScreenshotDRC = gImageSource == IMAGE_SOURCE_TV_AND_DRC || gImageSource == IMAGE_SOURCE_DRC; + screenshotCoolDown = 60; + } + } + } + } +} + DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, GX2ScanTarget scan_target) { + if ((takeScreenshotTV || takeScreenshotDRC)) { if (scan_target == GX2_SCAN_TARGET_TV && colorBuffer != nullptr && takeScreenshotTV) { DEBUG_FUNCTION_LINE("Lets take a screenshot from TV."); @@ -46,6 +78,8 @@ DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorB takeScreenshot((GX2ColorBuffer *) colorBuffer, scan_target, gDRCSurfaceFormat, gOutputFormat, gQuality); takeScreenshotDRC = false; } + } else if (screenshotCoolDown > 0) { + screenshotCoolDown--; } real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); } @@ -67,4 +101,5 @@ DECL_FUNCTION(void, GX2SetDRCBuffer, void *buffer, uint32_t buffer_size, uint32_ WUPS_MUST_REPLACE(VPADRead, WUPS_LOADER_LIBRARY_VPAD, VPADRead); WUPS_MUST_REPLACE(GX2CopyColorBufferToScanBuffer, WUPS_LOADER_LIBRARY_GX2, GX2CopyColorBufferToScanBuffer); WUPS_MUST_REPLACE(GX2SetTVBuffer, WUPS_LOADER_LIBRARY_GX2, GX2SetTVBuffer); -WUPS_MUST_REPLACE(GX2SetDRCBuffer, WUPS_LOADER_LIBRARY_GX2, GX2SetDRCBuffer); \ No newline at end of file +WUPS_MUST_REPLACE(GX2SetDRCBuffer, WUPS_LOADER_LIBRARY_GX2, GX2SetDRCBuffer); +WUPS_MUST_REPLACE(WPADRead, WUPS_LOADER_LIBRARY_PADSCORE, WPADRead); \ No newline at end of file diff --git a/src/utils/WUPSConfigItemButtonCombo.cpp b/src/utils/WUPSConfigItemButtonCombo.cpp index c2aa010..f4d092d 100644 --- a/src/utils/WUPSConfigItemButtonCombo.cpp +++ b/src/utils/WUPSConfigItemButtonCombo.cpp @@ -1,4 +1,5 @@ #include "WUPSConfigItemButtonCombo.h" +#include "utils/input.h" #include #include #include @@ -149,6 +150,9 @@ void checkForHold(ConfigItemButtonCombo *item) { VPAD_BUTTON_ZL | VPAD_BUTTON_ZR | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN | VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT | VPAD_BUTTON_STICK_L | VPAD_BUTTON_STICK_R | VPAD_BUTTON_PLUS | VPAD_BUTTON_MINUS | VPAD_BUTTON_TV; + KPADStatus kpad_data{}; + KPADError kpad_error; + while (true) { uint32_t buttonsHold = 0; VPADReadError vpad_error = VPAD_READ_UNINITIALIZED; @@ -158,6 +162,19 @@ void checkForHold(ConfigItemButtonCombo *item) { buttonsHold = vpad_data.hold; } + for (int i = 0; i < 4; i++) { + memset(&kpad_data, 0, sizeof(kpad_data)); + if (KPADReadEx((KPADChan) i, &kpad_data, 1, &kpad_error) > 0) { + if (kpad_error == KPAD_ERROR_OK && kpad_data.extensionType != 0xFF) { + if (kpad_data.extensionType == WPAD_EXT_CORE || kpad_data.extensionType == WPAD_EXT_NUNCHUK) { + buttonsHold |= remapWiiMoteButtons(kpad_data.hold); + } else { + buttonsHold |= remapClassicButtons(kpad_data.classic.hold); + } + } + } + } + buttonsHold &= mask; if (buttonsHold == lastHold) { diff --git a/src/utils/input.cpp b/src/utils/input.cpp new file mode 100644 index 0000000..f151057 --- /dev/null +++ b/src/utils/input.cpp @@ -0,0 +1,217 @@ +#include "input.h" + +uint32_t remapVPADtoWiimote(uint32_t buttons) { + uint32_t conv_buttons = 0; + if (buttons & VPAD_BUTTON_A) { + conv_buttons |= WPAD_BUTTON_A; + } + if (buttons & VPAD_BUTTON_B) { + conv_buttons |= WPAD_BUTTON_B; + } + if (buttons & VPAD_BUTTON_UP) { + conv_buttons |= WPAD_BUTTON_UP; + } + if (buttons & VPAD_BUTTON_DOWN) { + conv_buttons |= WPAD_BUTTON_DOWN; + } + if (buttons & VPAD_BUTTON_LEFT) { + conv_buttons |= WPAD_BUTTON_LEFT; + } + if (buttons & VPAD_BUTTON_RIGHT) { + conv_buttons |= WPAD_BUTTON_RIGHT; + } + if (buttons & VPAD_BUTTON_PLUS) { + conv_buttons |= WPAD_BUTTON_PLUS; + } + if (buttons & VPAD_BUTTON_MINUS) { + conv_buttons |= WPAD_BUTTON_MINUS; + } + return conv_buttons; +} + + +uint32_t remapVPADtoClassic(uint32_t buttons) { + uint32_t conv_buttons = 0; + if (buttons & VPAD_BUTTON_A) { + conv_buttons |= WPAD_CLASSIC_BUTTON_A; + } + if (buttons & VPAD_BUTTON_B) { + conv_buttons |= WPAD_CLASSIC_BUTTON_B; + } + if (buttons & VPAD_BUTTON_X) { + conv_buttons |= WPAD_CLASSIC_BUTTON_X; + } + if (buttons & VPAD_BUTTON_Y) { + conv_buttons |= WPAD_CLASSIC_BUTTON_Y; + } + if (buttons & VPAD_BUTTON_L) { + conv_buttons |= WPAD_CLASSIC_BUTTON_L; + } + if (buttons & VPAD_BUTTON_R) { + conv_buttons |= WPAD_CLASSIC_BUTTON_R; + } + if (buttons & VPAD_BUTTON_ZL) { + conv_buttons |= WPAD_CLASSIC_BUTTON_ZL; + } + if (buttons & VPAD_BUTTON_ZR) { + conv_buttons |= WPAD_CLASSIC_BUTTON_ZR; + } + if (buttons & VPAD_BUTTON_UP) { + conv_buttons |= WPAD_CLASSIC_BUTTON_UP; + } + if (buttons & VPAD_BUTTON_DOWN) { + conv_buttons |= WPAD_CLASSIC_BUTTON_DOWN; + } + if (buttons & VPAD_BUTTON_LEFT) { + conv_buttons |= WPAD_CLASSIC_BUTTON_LEFT; + } + if (buttons & VPAD_BUTTON_RIGHT) { + conv_buttons |= WPAD_CLASSIC_BUTTON_RIGHT; + } + if (buttons & VPAD_BUTTON_PLUS) { + conv_buttons |= WPAD_CLASSIC_BUTTON_PLUS; + } + if (buttons & VPAD_BUTTON_MINUS) { + conv_buttons |= WPAD_CLASSIC_BUTTON_MINUS; + } + return conv_buttons; +} + +uint32_t remapVPADtoPro(uint32_t buttons) { + uint32_t conv_buttons = 0; + if (buttons & VPAD_BUTTON_A) { + conv_buttons |= WPAD_PRO_BUTTON_A; + } + if (buttons & VPAD_BUTTON_B) { + conv_buttons |= WPAD_PRO_BUTTON_B; + } + if (buttons & VPAD_BUTTON_X) { + conv_buttons |= WPAD_PRO_BUTTON_X; + } + if (buttons & VPAD_BUTTON_Y) { + conv_buttons |= WPAD_PRO_BUTTON_Y; + } + if (buttons & VPAD_BUTTON_L) { + conv_buttons |= WPAD_PRO_TRIGGER_L; + } + if (buttons & VPAD_BUTTON_R) { + conv_buttons |= WPAD_PRO_TRIGGER_R; + } + if (buttons & VPAD_BUTTON_ZL) { + conv_buttons |= WPAD_PRO_TRIGGER_ZL; + } + if (buttons & VPAD_BUTTON_ZR) { + conv_buttons |= WPAD_PRO_TRIGGER_ZR; + } + if (buttons & VPAD_BUTTON_UP) { + conv_buttons |= WPAD_PRO_BUTTON_UP; + } + if (buttons & VPAD_BUTTON_DOWN) { + conv_buttons |= WPAD_PRO_BUTTON_DOWN; + } + if (buttons & VPAD_BUTTON_LEFT) { + conv_buttons |= WPAD_PRO_BUTTON_LEFT; + } + if (buttons & VPAD_BUTTON_RIGHT) { + conv_buttons |= WPAD_PRO_BUTTON_RIGHT; + } + if (buttons & VPAD_BUTTON_PLUS) { + conv_buttons |= WPAD_PRO_BUTTON_PLUS; + } + if (buttons & VPAD_BUTTON_MINUS) { + conv_buttons |= WPAD_PRO_BUTTON_MINUS; + } + return conv_buttons; +} + +uint32_t remapWiiMoteButtons(uint32_t buttons) { + uint32_t conv_buttons = 0; + + if (buttons & WPAD_BUTTON_LEFT) { + conv_buttons |= VPAD_BUTTON_LEFT; + } + + if (buttons & WPAD_BUTTON_RIGHT) { + conv_buttons |= VPAD_BUTTON_RIGHT; + } + + if (buttons & WPAD_BUTTON_DOWN) { + conv_buttons |= VPAD_BUTTON_DOWN; + } + + if (buttons & WPAD_BUTTON_UP) { + conv_buttons |= VPAD_BUTTON_UP; + } + + if (buttons & WPAD_BUTTON_PLUS) { + conv_buttons |= VPAD_BUTTON_PLUS; + } + + if (buttons & WPAD_BUTTON_B) { + conv_buttons |= VPAD_BUTTON_B; + } + + if (buttons & WPAD_BUTTON_A) { + conv_buttons |= VPAD_BUTTON_A; + } + + if (buttons & WPAD_BUTTON_MINUS) { + conv_buttons |= VPAD_BUTTON_MINUS; + } + + if (buttons & WPAD_BUTTON_HOME) { + conv_buttons |= VPAD_BUTTON_HOME; + } + return conv_buttons; +} + +uint32_t remapClassicButtons(uint32_t buttons) { + uint32_t conv_buttons = 0; + + if (buttons & WPAD_CLASSIC_BUTTON_LEFT) { + conv_buttons |= VPAD_BUTTON_LEFT; + } + if (buttons & WPAD_CLASSIC_BUTTON_RIGHT) { + conv_buttons |= VPAD_BUTTON_RIGHT; + } + if (buttons & WPAD_CLASSIC_BUTTON_DOWN) { + conv_buttons |= VPAD_BUTTON_DOWN; + } + if (buttons & WPAD_CLASSIC_BUTTON_UP) { + conv_buttons |= VPAD_BUTTON_UP; + } + if (buttons & WPAD_CLASSIC_BUTTON_PLUS) { + conv_buttons |= VPAD_BUTTON_PLUS; + } + if (buttons & WPAD_CLASSIC_BUTTON_X) { + conv_buttons |= VPAD_BUTTON_X; + } + if (buttons & WPAD_CLASSIC_BUTTON_Y) { + conv_buttons |= VPAD_BUTTON_Y; + } + if (buttons & WPAD_CLASSIC_BUTTON_B) { + conv_buttons |= VPAD_BUTTON_B; + } + if (buttons & WPAD_CLASSIC_BUTTON_A) { + conv_buttons |= VPAD_BUTTON_A; + } + if (buttons & WPAD_CLASSIC_BUTTON_MINUS) { + conv_buttons |= VPAD_BUTTON_MINUS; + } + if (buttons & WPAD_CLASSIC_BUTTON_HOME) { + conv_buttons |= VPAD_BUTTON_HOME; + } + if (buttons & WPAD_CLASSIC_BUTTON_ZR) { + conv_buttons |= VPAD_BUTTON_ZR; + } + if (buttons & WPAD_CLASSIC_BUTTON_ZL) { + conv_buttons |= VPAD_BUTTON_ZL; + } + if (buttons & WPAD_CLASSIC_BUTTON_R) { + conv_buttons |= VPAD_BUTTON_R; + } + if (buttons & WPAD_CLASSIC_BUTTON_L) { + conv_buttons |= VPAD_BUTTON_L; + } + return conv_buttons; +} \ No newline at end of file diff --git a/src/utils/input.h b/src/utils/input.h new file mode 100644 index 0000000..92607bf --- /dev/null +++ b/src/utils/input.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include + + +uint32_t remapVPADtoWiimote(uint32_t buttons); +uint32_t remapVPADtoClassic(uint32_t buttons); +uint32_t remapVPADtoPro(uint32_t buttons); + +uint32_t remapWiiMoteButtons(uint32_t buttons); +uint32_t remapClassicButtons(uint32_t buttons); \ No newline at end of file