Menus support all controllers

This commit is contained in:
Andrew Hawes 2023-06-06 09:29:53 +01:00 committed by Maschell
parent 10161be0a2
commit 4e821e4fa2
6 changed files with 194 additions and 39 deletions

1
.gitignore vendored
View File

@ -2,5 +2,6 @@
*.rpx *.rpx
build/ build/
.idea/ .idea/
.vscode/
cmake-build-debug/ cmake-build-debug/
CMakeLists.txt CMakeLists.txt

134
source/InputUtils.cpp Normal file
View File

@ -0,0 +1,134 @@
#include "InputUtils.h"
#include <padscore/kpad.h>
#include <padscore/wpad.h>
#include <vpad/input.h>
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();
}

17
source/InputUtils.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include <cstdint>
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();
};

View File

@ -1,6 +1,7 @@
#include "MenuUtils.h" #include "MenuUtils.h"
#include "ACTAccountInfo.h" #include "ACTAccountInfo.h"
#include "DrawUtils.h" #include "DrawUtils.h"
#include "InputUtils.h"
#include "icon_png.h" #include "icon_png.h"
#include "logger.h" #include "logger.h"
#include "utils.h" #include "utils.h"
@ -14,6 +15,7 @@
#include <malloc.h> #include <malloc.h>
#include <memory> #include <memory>
#include <nn/act/client_cpp.h> #include <nn/act/client_cpp.h>
#include <padscore/kpad.h>
#include <string> #include <string>
#include <sysapp/title.h> #include <sysapp/title.h>
#include <vector> #include <vector>
@ -28,15 +30,6 @@ const char *autoboot_config_strings[] = {
"vwii_homebrew_channel", "vwii_homebrew_channel",
}; };
template<typename... Args>
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_t>(size_s);
auto buf = std::make_unique<char[]>(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) { int32_t readAutobootOption(std::string &configPath) {
FILE *f = fopen(configPath.c_str(), "r"); FILE *f = fopen(configPath.c_str(), "r");
if (f) { if (f) {
@ -104,11 +97,11 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c
} }
bool redraw = true; 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--; selectedIndex--;
if (selectedIndex < 0) { if (selectedIndex < 0) {
@ -116,7 +109,7 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c
} }
redraw = true; redraw = true;
} else if (vpad.trigger & VPAD_BUTTON_DOWN) { } else if (buttons.trigger & VPAD_BUTTON_DOWN) {
if (!menu.empty()) { if (!menu.empty()) {
selectedIndex++; selectedIndex++;
@ -125,12 +118,12 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c
} }
redraw = true; redraw = true;
} }
} else if (vpad.trigger & VPAD_BUTTON_A) { } else if (buttons.trigger & VPAD_BUTTON_A) {
break; break;
} else if (vpad.trigger & VPAD_BUTTON_X) { } else if (buttons.trigger & VPAD_BUTTON_X) {
autobootIndex = -1; autobootIndex = -1;
redraw = true; redraw = true;
} else if (vpad.trigger & VPAD_BUTTON_Y) { } else if (buttons.trigger & VPAD_BUTTON_Y) {
autobootIndex = selectedIndex; autobootIndex = selectedIndex;
redraw = true; redraw = true;
} }
@ -208,7 +201,6 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c
return selected; return selected;
} }
nn::act::SlotNo handleAccountSelectScreen(const std::vector<std::shared_ptr<AccountInfo>> &data) { nn::act::SlotNo handleAccountSelectScreen(const std::vector<std::shared_ptr<AccountInfo>> &data) {
auto screenBuffer = DrawUtils::InitOSScreen(); auto screenBuffer = DrawUtils::InitOSScreen();
if (!screenBuffer) { if (!screenBuffer) {
@ -225,21 +217,21 @@ nn::act::SlotNo handleAccountSelectScreen(const std::vector<std::shared_ptr<Acco
int32_t selected = 0; int32_t selected = 0;
bool redraw = true; 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) {
if (selected > 0) { if (selected > 0) {
selected--; selected--;
redraw = true; redraw = true;
} }
} else if (vpad.trigger & VPAD_BUTTON_DOWN) { } else if (buttons.trigger & VPAD_BUTTON_DOWN) {
if (selected < (int32_t) data.size() - 1) { if (selected < (int32_t) data.size() - 1) {
selected++; selected++;
redraw = true; redraw = true;
} }
} else if (vpad.trigger & VPAD_BUTTON_A) { } else if (buttons.trigger & VPAD_BUTTON_A) {
break; break;
} }
@ -392,12 +384,11 @@ void handleUpdateWarningScreen() {
DrawUtils::endDraw(); DrawUtils::endDraw();
while (true) { while (true) {
VPADStatus vpad{}; InputUtils::InputData buttons = InputUtils::getControllerInput();
VPADRead(VPAD_CHAN_0, &vpad, 1, nullptr);
if (vpad.trigger & VPAD_BUTTON_A) { if (buttons.trigger & VPAD_BUTTON_A) {
break; break;
} else if (vpad.trigger & VPAD_BUTTON_B) { } else if (buttons.trigger & VPAD_BUTTON_B) {
f = fopen(UPDATE_SKIP_PATH, "w"); f = fopen(UPDATE_SKIP_PATH, "w");
if (f) { if (f) {
// It's **really** important to have this text on the stack. // 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. // When an unexpected disc was inserted we need to eject it first.
bool allowDisc = !wrongDiscInserted; 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; result = false;
break; break;
} }

View File

@ -1,5 +1,6 @@
#include "BootUtils.h" #include "BootUtils.h"
#include "DrawUtils.h" #include "DrawUtils.h"
#include "InputUtils.h"
#include "MenuUtils.h" #include "MenuUtils.h"
#include "QuickStartUtils.h" #include "QuickStartUtils.h"
#include "StorageUtils.h" #include "StorageUtils.h"
@ -9,6 +10,7 @@
#include <gx2/state.h> #include <gx2/state.h>
#include <malloc.h> #include <malloc.h>
#include <mocha/mocha.h> #include <mocha/mocha.h>
#include <padscore/kpad.h>
#include <sndcore2/core.h> #include <sndcore2/core.h>
#include <string> #include <string>
#include <sys/stat.h> #include <sys/stat.h>
@ -33,13 +35,14 @@ int32_t main(int32_t argc, char **argv) {
AXInit(); AXInit();
AXQuit(); AXQuit();
InputUtils::Init();
// Clear screen to avoid screen corruptions when loading the Wii U Menu // Clear screen to avoid screen corruptions when loading the Wii U Menu
clearScreen(); clearScreen();
initExternalStorage(); initExternalStorage();
if (getQuickBoot()) { if (getQuickBoot()) {
deinitLogging(); deinitLogging();
return 0; return 0;
} }
@ -48,16 +51,12 @@ int32_t main(int32_t argc, char **argv) {
OSFatal("AutobootModule: Mocha_InitLibrary failed"); OSFatal("AutobootModule: Mocha_InitLibrary failed");
} }
VPADStatus vpad{};
// Buffer vpad read.
VPADRead(VPAD_CHAN_0, &vpad, 1, nullptr);
FSAInit(); FSAInit();
auto client = FSAAddClient(nullptr); auto client = FSAAddClient(nullptr);
if (client > 0) { if (client > 0) {
if (Mocha_UnlockFSClientEx(client) == MOCHA_RESULT_SUCCESS) { if (Mocha_UnlockFSClientEx(client) == MOCHA_RESULT_SUCCESS) {
// test if the update folder exists // test if the update folder exists
FSADirectoryHandle dirHandle; FSADirectoryHandle dirHandle{};
if (FSAOpenDir(client, "/vol/storage_mlc01/sys/update", &dirHandle) >= 0) { if (FSAOpenDir(client, "/vol/storage_mlc01/sys/update", &dirHandle) >= 0) {
FSACloseDir(client, dirHandle); FSACloseDir(client, dirHandle);
handleUpdateWarningScreen(); handleUpdateWarningScreen();
@ -71,6 +70,8 @@ int32_t main(int32_t argc, char **argv) {
DEBUG_FUNCTION_LINE_ERR("Failed to create FSA Client"); DEBUG_FUNCTION_LINE_ERR("Failed to create FSA Client");
} }
InputUtils::InputData buttons = InputUtils::getControllerInput();
bool showvHBL = getVWiiHBLTitleId() != 0; bool showvHBL = getVWiiHBLTitleId() != 0;
bool showHBL = false; bool showHBL = false;
std::string configPath = "fs:/vol/external01/wiiu/autoboot.cfg"; std::string configPath = "fs:/vol/external01/wiiu/autoboot.cfg";
@ -99,7 +100,7 @@ int32_t main(int32_t argc, char **argv) {
if ((bootSelection == -1) || if ((bootSelection == -1) ||
(bootSelection == BOOT_OPTION_HOMEBREW_LAUNCHER && !showHBL) || (bootSelection == BOOT_OPTION_HOMEBREW_LAUNCHER && !showHBL) ||
(bootSelection == BOOT_OPTION_VWII_HOMEBREW_CHANNEL && !showvHBL) || (bootSelection == BOOT_OPTION_VWII_HOMEBREW_CHANNEL && !showvHBL) ||
(vpad.hold & VPAD_BUTTON_PLUS)) { (buttons.hold & VPAD_BUTTON_PLUS)) {
bootSelection = handleMenuScreen(configPath, bootSelection, menu); bootSelection = handleMenuScreen(configPath, bootSelection, menu);
} }
@ -133,6 +134,8 @@ int32_t main(int32_t argc, char **argv) {
bootWiiUMenu(); bootWiiUMenu();
} }
InputUtils::DeInit();
Mocha_DeInitLibrary(); Mocha_DeInitLibrary();
deinitLogging(); deinitLogging();

View File

@ -19,4 +19,13 @@ std::shared_ptr<T> make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std::
return std::shared_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...)); return std::shared_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...));
} }
template<typename... Args>
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_t>(size_s);
auto buf = std::make_unique<char[]>(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); bool GetTitleIdOfDisc(uint64_t *titleId, bool *discPresent);