From 4e821e4fa22b85eee569d4b2384e6c528bd6944f Mon Sep 17 00:00:00 2001 From: Andrew Hawes <117602754+Andrew1Hawes@users.noreply.github.com> Date: Tue, 6 Jun 2023 09:29:53 +0100 Subject: [PATCH] Menus support all controllers --- .gitignore | 1 + source/InputUtils.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++ source/InputUtils.h | 17 ++++++ source/MenuUtils.cpp | 55 ++++++++--------- source/main.cpp | 17 +++--- source/utils.h | 9 +++ 6 files changed, 194 insertions(+), 39 deletions(-) create mode 100644 source/InputUtils.cpp create mode 100644 source/InputUtils.h diff --git a/.gitignore b/.gitignore index 5e1c8ec..aadaac0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ *.rpx build/ .idea/ +.vscode/ cmake-build-debug/ CMakeLists.txt diff --git a/source/InputUtils.cpp b/source/InputUtils.cpp new file mode 100644 index 0000000..d910ba1 --- /dev/null +++ b/source/InputUtils.cpp @@ -0,0 +1,134 @@ +#include "InputUtils.h" +#include +#include +#include + +uint32_t remapWiiMoteButtons(uint32_t buttons) { + uint32_t convButtons = 0; + + if (buttons & WPAD_BUTTON_LEFT) + convButtons |= VPAD_BUTTON_LEFT; + + if (buttons & WPAD_BUTTON_RIGHT) + convButtons |= VPAD_BUTTON_RIGHT; + + if (buttons & WPAD_BUTTON_DOWN) + convButtons |= VPAD_BUTTON_DOWN; + + if (buttons & WPAD_BUTTON_UP) + convButtons |= VPAD_BUTTON_UP; + + if (buttons & WPAD_BUTTON_PLUS) + convButtons |= VPAD_BUTTON_PLUS; + + if (buttons & WPAD_BUTTON_2) + convButtons |= VPAD_BUTTON_Y; + + if (buttons & WPAD_BUTTON_1) + convButtons |= VPAD_BUTTON_X; + + if (buttons & WPAD_BUTTON_B) + convButtons |= VPAD_BUTTON_B; + + if (buttons & WPAD_BUTTON_A) + convButtons |= VPAD_BUTTON_A; + + if (buttons & WPAD_BUTTON_MINUS) + convButtons |= VPAD_BUTTON_MINUS; + + if (buttons & WPAD_BUTTON_HOME) + convButtons |= VPAD_BUTTON_HOME; + + return convButtons; +} + +uint32_t remapClassicButtons(uint32_t buttons) { + uint32_t convButtons = 0; + + if (buttons & WPAD_CLASSIC_BUTTON_LEFT) + convButtons |= VPAD_BUTTON_LEFT; + + if (buttons & WPAD_CLASSIC_BUTTON_RIGHT) + convButtons |= VPAD_BUTTON_RIGHT; + + if (buttons & WPAD_CLASSIC_BUTTON_DOWN) + convButtons |= VPAD_BUTTON_DOWN; + + if (buttons & WPAD_CLASSIC_BUTTON_UP) + convButtons |= VPAD_BUTTON_UP; + + if (buttons & WPAD_CLASSIC_BUTTON_PLUS) + convButtons |= VPAD_BUTTON_PLUS; + + if (buttons & WPAD_CLASSIC_BUTTON_X) + convButtons |= VPAD_BUTTON_X; + + if (buttons & WPAD_CLASSIC_BUTTON_Y) + convButtons |= VPAD_BUTTON_Y; + + if (buttons & WPAD_CLASSIC_BUTTON_B) + convButtons |= VPAD_BUTTON_B; + + if (buttons & WPAD_CLASSIC_BUTTON_A) + convButtons |= VPAD_BUTTON_A; + + if (buttons & WPAD_CLASSIC_BUTTON_MINUS) + convButtons |= VPAD_BUTTON_MINUS; + + if (buttons & WPAD_CLASSIC_BUTTON_HOME) + convButtons |= VPAD_BUTTON_HOME; + + if (buttons & WPAD_CLASSIC_BUTTON_ZR) + convButtons |= VPAD_BUTTON_ZR; + + if (buttons & WPAD_CLASSIC_BUTTON_ZL) + convButtons |= VPAD_BUTTON_ZL; + + if (buttons & WPAD_CLASSIC_BUTTON_R) + convButtons |= VPAD_BUTTON_R; + + if (buttons & WPAD_CLASSIC_BUTTON_L) + convButtons |= VPAD_BUTTON_L; + + return convButtons; +} + +InputUtils::InputData InputUtils::getControllerInput() { + InputData inputData{}; + VPADStatus vpadStatus{}; + VPADReadError vpadError = VPAD_READ_UNINITIALIZED; + if (VPADRead(VPAD_CHAN_0, &vpadStatus, 1, &vpadError) > 0 && vpadError == VPAD_READ_SUCCESS) { + inputData.trigger = vpadStatus.trigger; + inputData.hold = vpadStatus.hold; + inputData.release = vpadStatus.release; + } + + KPADStatus kpadStatus{}; + KPADError kpadError = KPAD_ERROR_UNINITIALIZED; + for (int32_t i = 0; i < 4; i++) { + if (KPADReadEx((KPADChan) i, &kpadStatus, 1, &kpadError) > 0) { + if (kpadError == KPAD_ERROR_OK && kpadStatus.extensionType != 0xFF) { + if (kpadStatus.extensionType == WPAD_EXT_CORE || kpadStatus.extensionType == WPAD_EXT_NUNCHUK) { + inputData.trigger |= remapWiiMoteButtons(kpadStatus.trigger); + inputData.hold |= remapWiiMoteButtons(kpadStatus.hold); + inputData.release |= remapWiiMoteButtons(kpadStatus.release); + } else { + inputData.trigger |= remapClassicButtons(kpadStatus.classic.trigger); + inputData.hold |= remapClassicButtons(kpadStatus.classic.hold); + inputData.release |= remapClassicButtons(kpadStatus.classic.release); + } + } + } + } + + return inputData; +} + +void InputUtils::Init() { + KPADInit(); + WPADEnableURCC(1); +} + +void InputUtils::DeInit() { + KPADShutdown(); +} \ No newline at end of file diff --git a/source/InputUtils.h b/source/InputUtils.h new file mode 100644 index 0000000..4e44544 --- /dev/null +++ b/source/InputUtils.h @@ -0,0 +1,17 @@ +#pragma once +#include + + +class InputUtils { +public: + typedef struct InputData { + uint32_t trigger = 0; + uint32_t hold = 0; + uint32_t release = 0; + } InputData; + + static void Init(); + static void DeInit(); + + static InputData getControllerInput(); +}; diff --git a/source/MenuUtils.cpp b/source/MenuUtils.cpp index 7b4b5d2..2d80a17 100644 --- a/source/MenuUtils.cpp +++ b/source/MenuUtils.cpp @@ -1,6 +1,7 @@ #include "MenuUtils.h" #include "ACTAccountInfo.h" #include "DrawUtils.h" +#include "InputUtils.h" #include "icon_png.h" #include "logger.h" #include "utils.h" @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -28,15 +30,6 @@ const char *autoboot_config_strings[] = { "vwii_homebrew_channel", }; -template -std::string string_format(const std::string &format, Args... args) { - int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0' - auto size = static_cast(size_s); - auto buf = std::make_unique(size); - std::snprintf(buf.get(), size, format.c_str(), args...); - return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside -} - int32_t readAutobootOption(std::string &configPath) { FILE *f = fopen(configPath.c_str(), "r"); if (f) { @@ -104,11 +97,11 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c } bool redraw = true; - while (true) { - VPADStatus vpad{}; - VPADRead(VPAD_CHAN_0, &vpad, 1, nullptr); - if (vpad.trigger & VPAD_BUTTON_UP) { + while (true) { + InputUtils::InputData buttons = InputUtils::getControllerInput(); + + if (buttons.trigger & VPAD_BUTTON_UP) { selectedIndex--; if (selectedIndex < 0) { @@ -116,7 +109,7 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c } redraw = true; - } else if (vpad.trigger & VPAD_BUTTON_DOWN) { + } else if (buttons.trigger & VPAD_BUTTON_DOWN) { if (!menu.empty()) { selectedIndex++; @@ -125,12 +118,12 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c } redraw = true; } - } else if (vpad.trigger & VPAD_BUTTON_A) { + } else if (buttons.trigger & VPAD_BUTTON_A) { break; - } else if (vpad.trigger & VPAD_BUTTON_X) { + } else if (buttons.trigger & VPAD_BUTTON_X) { autobootIndex = -1; redraw = true; - } else if (vpad.trigger & VPAD_BUTTON_Y) { + } else if (buttons.trigger & VPAD_BUTTON_Y) { autobootIndex = selectedIndex; redraw = true; } @@ -208,7 +201,6 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c return selected; } - nn::act::SlotNo handleAccountSelectScreen(const std::vector> &data) { auto screenBuffer = DrawUtils::InitOSScreen(); if (!screenBuffer) { @@ -225,21 +217,21 @@ nn::act::SlotNo handleAccountSelectScreen(const std::vector 0) { selected--; redraw = true; } - } else if (vpad.trigger & VPAD_BUTTON_DOWN) { + } else if (buttons.trigger & VPAD_BUTTON_DOWN) { if (selected < (int32_t) data.size() - 1) { selected++; redraw = true; } - } else if (vpad.trigger & VPAD_BUTTON_A) { + } else if (buttons.trigger & VPAD_BUTTON_A) { break; } @@ -392,12 +384,11 @@ void handleUpdateWarningScreen() { DrawUtils::endDraw(); while (true) { - VPADStatus vpad{}; - VPADRead(VPAD_CHAN_0, &vpad, 1, nullptr); + InputUtils::InputData buttons = InputUtils::getControllerInput(); - if (vpad.trigger & VPAD_BUTTON_A) { + if (buttons.trigger & VPAD_BUTTON_A) { break; - } else if (vpad.trigger & VPAD_BUTTON_B) { + } else if (buttons.trigger & VPAD_BUTTON_B) { f = fopen(UPDATE_SKIP_PATH, "w"); if (f) { // It's **really** important to have this text on the stack. @@ -493,11 +484,11 @@ bool handleDiscInsertScreen(uint64_t expectedTitleId, uint64_t *titleIdToLaunch) // When an unexpected disc was inserted we need to eject it first. bool allowDisc = !wrongDiscInserted; - while (true) { - VPADStatus vpad{}; - VPADRead(VPAD_CHAN_0, &vpad, 1, nullptr); - if (vpad.trigger & VPAD_BUTTON_A) { + while (true) { + InputUtils::InputData buttons = InputUtils::getControllerInput(); + + if (buttons.trigger & VPAD_BUTTON_A) { result = false; break; } diff --git a/source/main.cpp b/source/main.cpp index 0348fa8..bbb59ca 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,5 +1,6 @@ #include "BootUtils.h" #include "DrawUtils.h" +#include "InputUtils.h" #include "MenuUtils.h" #include "QuickStartUtils.h" #include "StorageUtils.h" @@ -9,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -33,13 +35,14 @@ int32_t main(int32_t argc, char **argv) { AXInit(); AXQuit(); + InputUtils::Init(); + // Clear screen to avoid screen corruptions when loading the Wii U Menu clearScreen(); initExternalStorage(); if (getQuickBoot()) { - deinitLogging(); return 0; } @@ -48,16 +51,12 @@ int32_t main(int32_t argc, char **argv) { OSFatal("AutobootModule: Mocha_InitLibrary failed"); } - VPADStatus vpad{}; - // Buffer vpad read. - VPADRead(VPAD_CHAN_0, &vpad, 1, nullptr); - FSAInit(); auto client = FSAAddClient(nullptr); if (client > 0) { if (Mocha_UnlockFSClientEx(client) == MOCHA_RESULT_SUCCESS) { // test if the update folder exists - FSADirectoryHandle dirHandle; + FSADirectoryHandle dirHandle{}; if (FSAOpenDir(client, "/vol/storage_mlc01/sys/update", &dirHandle) >= 0) { FSACloseDir(client, dirHandle); handleUpdateWarningScreen(); @@ -71,6 +70,8 @@ int32_t main(int32_t argc, char **argv) { DEBUG_FUNCTION_LINE_ERR("Failed to create FSA Client"); } + InputUtils::InputData buttons = InputUtils::getControllerInput(); + bool showvHBL = getVWiiHBLTitleId() != 0; bool showHBL = false; std::string configPath = "fs:/vol/external01/wiiu/autoboot.cfg"; @@ -99,7 +100,7 @@ int32_t main(int32_t argc, char **argv) { if ((bootSelection == -1) || (bootSelection == BOOT_OPTION_HOMEBREW_LAUNCHER && !showHBL) || (bootSelection == BOOT_OPTION_VWII_HOMEBREW_CHANNEL && !showvHBL) || - (vpad.hold & VPAD_BUTTON_PLUS)) { + (buttons.hold & VPAD_BUTTON_PLUS)) { bootSelection = handleMenuScreen(configPath, bootSelection, menu); } @@ -133,6 +134,8 @@ int32_t main(int32_t argc, char **argv) { bootWiiUMenu(); } + InputUtils::DeInit(); + Mocha_DeInitLibrary(); deinitLogging(); diff --git a/source/utils.h b/source/utils.h index ba78faf..fd78205 100644 --- a/source/utils.h +++ b/source/utils.h @@ -19,4 +19,13 @@ std::shared_ptr make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std:: return std::shared_ptr(new (std::nothrow) T(std::forward(args)...)); } +template +std::string string_format(const std::string &format, Args... args) { + int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0' + auto size = static_cast(size_s); + auto buf = std::make_unique(size); + std::snprintf(buf.get(), size, format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside +} + bool GetTitleIdOfDisc(uint64_t *titleId, bool *discPresent); \ No newline at end of file