mirror of
https://github.com/wiiu-env/AutobootModule.git
synced 2024-11-22 10:59:15 +01:00
Implement support for pairing a controller or GamePad
This commit is contained in:
parent
4e821e4fa2
commit
6954a7f9f5
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <vpad/input.h>
|
||||||
|
|
||||||
class InputUtils {
|
class InputUtils {
|
||||||
public:
|
public:
|
||||||
|
@ -2,24 +2,21 @@
|
|||||||
#include "ACTAccountInfo.h"
|
#include "ACTAccountInfo.h"
|
||||||
#include "DrawUtils.h"
|
#include "DrawUtils.h"
|
||||||
#include "InputUtils.h"
|
#include "InputUtils.h"
|
||||||
|
#include "PairUtils.h"
|
||||||
#include "icon_png.h"
|
#include "icon_png.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include <coreinit/debug.h>
|
#include <coreinit/debug.h>
|
||||||
#include <coreinit/mcp.h>
|
|
||||||
#include <coreinit/screen.h>
|
#include <coreinit/screen.h>
|
||||||
#include <coreinit/thread.h>
|
#include <coreinit/thread.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <gx2/state.h>
|
#include <gx2/state.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#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>
|
||||||
#include <vpad/input.h>
|
|
||||||
|
|
||||||
#define AUTOBOOT_MODULE_VERSION "v0.1.3"
|
#define AUTOBOOT_MODULE_VERSION "v0.1.3"
|
||||||
|
|
||||||
@ -59,6 +56,48 @@ void writeAutobootOption(std::string &configPath, int32_t autobootOption) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawMenuScreen(const std::map<uint32_t, std::string> &menu, uint32_t selectedIndex, uint32_t autobootIndex) {
|
||||||
|
DrawUtils::beginDraw();
|
||||||
|
DrawUtils::clear(COLOR_BACKGROUND);
|
||||||
|
|
||||||
|
// draw buttons
|
||||||
|
uint32_t index = 8 + 24 + 8 + 4;
|
||||||
|
for (uint32_t i = 0; i < menu.size(); i++) {
|
||||||
|
if (i == (uint32_t) selectedIndex) {
|
||||||
|
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16 * 2, 44, 4, COLOR_BORDER_HIGHLIGHTED);
|
||||||
|
} else {
|
||||||
|
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16 * 2, 44, 2, (i == (uint32_t) autobootIndex) ? COLOR_AUTOBOOT : COLOR_BORDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string curName = std::next(menu.begin(), i)->second;
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(24);
|
||||||
|
DrawUtils::setFontColor((i == (uint32_t) autobootIndex) ? COLOR_AUTOBOOT : COLOR_TEXT);
|
||||||
|
DrawUtils::print(16 * 2, index + 8 + 24, curName.c_str());
|
||||||
|
index += 42 + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawUtils::setFontColor(COLOR_TEXT);
|
||||||
|
|
||||||
|
// draw top bar
|
||||||
|
DrawUtils::setFontSize(24);
|
||||||
|
DrawUtils::drawPNG(16, 2, icon_png);
|
||||||
|
DrawUtils::print(64 + 2, 6 + 24, "Boot Selector");
|
||||||
|
DrawUtils::drawRectFilled(8, 8 + 24 + 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_WHITE);
|
||||||
|
DrawUtils::setFontSize(16);
|
||||||
|
DrawUtils::print(SCREEN_WIDTH - 16, 6 + 24, AUTOBOOT_MODULE_VERSION AUTOBOOT_MODULE_VERSION_EXTRA, true);
|
||||||
|
|
||||||
|
// draw bottom bar
|
||||||
|
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_WHITE);
|
||||||
|
DrawUtils::setFontSize(18);
|
||||||
|
DrawUtils::print(16, SCREEN_HEIGHT - 8, "\ue07d Navigate ");
|
||||||
|
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 8, "\ue000 Choose", true);
|
||||||
|
const char *autobootHints = "\ue002/\ue046 Clear Autoboot / \ue003/\ue045 Select Autoboot";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(autobootHints) / 2, SCREEN_HEIGHT - 8, autobootHints, true);
|
||||||
|
|
||||||
|
DrawUtils::endDraw();
|
||||||
|
}
|
||||||
|
|
||||||
int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, const std::map<uint32_t, std::string> &menu) {
|
int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, const std::map<uint32_t, std::string> &menu) {
|
||||||
auto screenBuffer = DrawUtils::InitOSScreen();
|
auto screenBuffer = DrawUtils::InitOSScreen();
|
||||||
if (!screenBuffer) {
|
if (!screenBuffer) {
|
||||||
@ -96,80 +135,41 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool redraw = true;
|
|
||||||
|
|
||||||
while (true) {
|
{
|
||||||
InputUtils::InputData buttons = InputUtils::getControllerInput();
|
PairMenu pairMenu;
|
||||||
|
|
||||||
if (buttons.trigger & VPAD_BUTTON_UP) {
|
while (true) {
|
||||||
selectedIndex--;
|
if (pairMenu.ProcessPairScreen()) {
|
||||||
|
continue;
|
||||||
if (selectedIndex < 0) {
|
|
||||||
selectedIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw = true;
|
InputUtils::InputData input = InputUtils::getControllerInput();
|
||||||
} else if (buttons.trigger & VPAD_BUTTON_DOWN) {
|
if (input.trigger & VPAD_BUTTON_UP) {
|
||||||
if (!menu.empty()) {
|
selectedIndex--;
|
||||||
selectedIndex++;
|
|
||||||
|
|
||||||
if ((uint32_t) selectedIndex >= menu.size()) {
|
if (selectedIndex < 0) {
|
||||||
selectedIndex = menu.size() - 1;
|
selectedIndex = 0;
|
||||||
}
|
|
||||||
redraw = true;
|
|
||||||
}
|
|
||||||
} else if (buttons.trigger & VPAD_BUTTON_A) {
|
|
||||||
break;
|
|
||||||
} else if (buttons.trigger & VPAD_BUTTON_X) {
|
|
||||||
autobootIndex = -1;
|
|
||||||
redraw = true;
|
|
||||||
} else if (buttons.trigger & VPAD_BUTTON_Y) {
|
|
||||||
autobootIndex = selectedIndex;
|
|
||||||
redraw = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (redraw) {
|
|
||||||
DrawUtils::beginDraw();
|
|
||||||
DrawUtils::clear(COLOR_BACKGROUND);
|
|
||||||
|
|
||||||
// draw buttons
|
|
||||||
uint32_t index = 8 + 24 + 8 + 4;
|
|
||||||
for (uint32_t i = 0; i < menu.size(); i++) {
|
|
||||||
if (i == (uint32_t) selectedIndex) {
|
|
||||||
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16 * 2, 44, 4, COLOR_BORDER_HIGHLIGHTED);
|
|
||||||
} else {
|
|
||||||
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16 * 2, 44, 2, (i == (uint32_t) autobootIndex) ? COLOR_AUTOBOOT : COLOR_BORDER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string curName = std::next(menu.begin(), i)->second;
|
} else if (input.trigger & VPAD_BUTTON_DOWN) {
|
||||||
|
if (!menu.empty()) {
|
||||||
|
selectedIndex++;
|
||||||
|
|
||||||
DrawUtils::setFontSize(24);
|
if ((uint32_t) selectedIndex >= menu.size()) {
|
||||||
DrawUtils::setFontColor((i == (uint32_t) autobootIndex) ? COLOR_AUTOBOOT : COLOR_TEXT);
|
selectedIndex = menu.size() - 1;
|
||||||
DrawUtils::print(16 * 2, index + 8 + 24, curName.c_str());
|
}
|
||||||
index += 42 + 8;
|
}
|
||||||
|
} else if (input.trigger & VPAD_BUTTON_A) {
|
||||||
|
break;
|
||||||
|
} else if (input.trigger & (VPAD_BUTTON_X | VPAD_BUTTON_MINUS)) {
|
||||||
|
autobootIndex = -1;
|
||||||
|
} else if (input.trigger & (VPAD_BUTTON_Y | VPAD_BUTTON_PLUS)) {
|
||||||
|
autobootIndex = selectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawUtils::setFontColor(COLOR_TEXT);
|
|
||||||
|
|
||||||
// draw top bar
|
drawMenuScreen(menu, selectedIndex, autobootIndex);
|
||||||
DrawUtils::setFontSize(24);
|
|
||||||
DrawUtils::drawPNG(16, 2, icon_png);
|
|
||||||
DrawUtils::print(64 + 2, 6 + 24, "Boot Selector");
|
|
||||||
DrawUtils::drawRectFilled(8, 8 + 24 + 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_WHITE);
|
|
||||||
DrawUtils::setFontSize(16);
|
|
||||||
DrawUtils::print(SCREEN_WIDTH - 16, 6 + 24, AUTOBOOT_MODULE_VERSION AUTOBOOT_MODULE_VERSION_EXTRA, true);
|
|
||||||
|
|
||||||
// draw bottom bar
|
|
||||||
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_WHITE);
|
|
||||||
DrawUtils::setFontSize(18);
|
|
||||||
DrawUtils::print(16, SCREEN_HEIGHT - 8, "\ue07d Navigate ");
|
|
||||||
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 8, "\ue000 Choose", true);
|
|
||||||
const char *autobootHints = "\ue002 Clear Autoboot / \ue003 Select Autoboot";
|
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(autobootHints) / 2, SCREEN_HEIGHT - 8, autobootHints, true);
|
|
||||||
|
|
||||||
DrawUtils::endDraw();
|
|
||||||
|
|
||||||
redraw = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,26 +216,27 @@ nn::act::SlotNo handleAccountSelectScreen(const std::vector<std::shared_ptr<Acco
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t selected = 0;
|
int32_t selected = 0;
|
||||||
bool redraw = true;
|
{
|
||||||
|
PairMenu pairMenu;
|
||||||
while (true) {
|
while (true) {
|
||||||
InputUtils::InputData buttons = InputUtils::getControllerInput();
|
if (pairMenu.ProcessPairScreen()) {
|
||||||
|
continue;
|
||||||
if (buttons.trigger & VPAD_BUTTON_UP) {
|
|
||||||
if (selected > 0) {
|
|
||||||
selected--;
|
|
||||||
redraw = true;
|
|
||||||
}
|
}
|
||||||
} else if (buttons.trigger & VPAD_BUTTON_DOWN) {
|
|
||||||
if (selected < (int32_t) data.size() - 1) {
|
|
||||||
selected++;
|
|
||||||
redraw = true;
|
|
||||||
}
|
|
||||||
} else if (buttons.trigger & VPAD_BUTTON_A) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (redraw) {
|
InputUtils::InputData input = InputUtils::getControllerInput();
|
||||||
|
if (input.trigger & VPAD_BUTTON_UP) {
|
||||||
|
if (selected > 0) {
|
||||||
|
selected--;
|
||||||
|
}
|
||||||
|
} else if (input.trigger & VPAD_BUTTON_DOWN) {
|
||||||
|
if (selected < (int32_t) data.size() - 1) {
|
||||||
|
selected++;
|
||||||
|
}
|
||||||
|
} else if (input.trigger & VPAD_BUTTON_A) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DrawUtils::beginDraw();
|
DrawUtils::beginDraw();
|
||||||
DrawUtils::clear(COLOR_BACKGROUND);
|
DrawUtils::clear(COLOR_BACKGROUND);
|
||||||
|
|
||||||
@ -306,8 +307,6 @@ nn::act::SlotNo handleAccountSelectScreen(const std::vector<std::shared_ptr<Acco
|
|||||||
}
|
}
|
||||||
|
|
||||||
DrawUtils::endDraw();
|
DrawUtils::endDraw();
|
||||||
|
|
||||||
redraw = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,6 +333,41 @@ nn::act::SlotNo handleAccountSelectScreen(const std::vector<std::shared_ptr<Acco
|
|||||||
return resultSlot;
|
return resultSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawUpdateWarningScreen() {
|
||||||
|
DrawUtils::beginDraw();
|
||||||
|
DrawUtils::clear(COLOR_BACKGROUND_WARN);
|
||||||
|
|
||||||
|
DrawUtils::setFontColor(COLOR_TEXT);
|
||||||
|
|
||||||
|
// draw top bar
|
||||||
|
DrawUtils::setFontSize(48);
|
||||||
|
const char *title = "! Warning !";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 48 + 8, title, true);
|
||||||
|
DrawUtils::drawRectFilled(8, 48 + 8 + 16, SCREEN_WIDTH - 8 * 2, 3, COLOR_WHITE);
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(24);
|
||||||
|
|
||||||
|
const char *message = "The update folder currently exists and is not a file.";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(message) / 2, SCREEN_HEIGHT / 2 - 48, message, true);
|
||||||
|
message = "Your system might not be blocking updates properly!";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(message) / 2, SCREEN_HEIGHT / 2 - 24, message, true);
|
||||||
|
message = "See https://wiiu.hacks.guide/#/block-updates for more information.";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(message) / 2, SCREEN_HEIGHT / 2 + 0, message, true);
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(16);
|
||||||
|
|
||||||
|
message = "Press the SYNC Button on the Wii U console to connect a controller or GamePad.";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(message) / 2, SCREEN_HEIGHT - 48, message, true);
|
||||||
|
|
||||||
|
// draw bottom bar
|
||||||
|
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_WHITE);
|
||||||
|
DrawUtils::setFontSize(18);
|
||||||
|
const char *exitHints = "\ue000 Continue / \ue001 Don't show this again";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(exitHints) / 2, SCREEN_HEIGHT - 8, exitHints, true);
|
||||||
|
|
||||||
|
DrawUtils::endDraw();
|
||||||
|
}
|
||||||
|
|
||||||
void handleUpdateWarningScreen() {
|
void handleUpdateWarningScreen() {
|
||||||
FILE *f = fopen(UPDATE_SKIP_PATH, "r");
|
FILE *f = fopen(UPDATE_SKIP_PATH, "r");
|
||||||
if (f) {
|
if (f) {
|
||||||
@ -355,53 +389,35 @@ void handleUpdateWarningScreen() {
|
|||||||
OSFatal("Failed to init font");
|
OSFatal("Failed to init font");
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawUtils::beginDraw();
|
{
|
||||||
DrawUtils::clear(COLOR_BACKGROUND_WARN);
|
PairMenu pairMenu;
|
||||||
|
|
||||||
DrawUtils::setFontColor(COLOR_TEXT);
|
while (true) {
|
||||||
|
if (pairMenu.ProcessPairScreen()) {
|
||||||
// draw top bar
|
continue;
|
||||||
DrawUtils::setFontSize(48);
|
}
|
||||||
const char *title = "! Warning !";
|
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 48 + 8, title, true);
|
drawUpdateWarningScreen();
|
||||||
DrawUtils::drawRectFilled(8, 48 + 8 + 16, SCREEN_WIDTH - 8 * 2, 3, COLOR_WHITE);
|
|
||||||
|
InputUtils::InputData input = InputUtils::getControllerInput();
|
||||||
DrawUtils::setFontSize(24);
|
if (input.trigger & VPAD_BUTTON_A) {
|
||||||
|
break;
|
||||||
const char *message = "The update folder currently exists and is not a file.";
|
} else if (input.trigger & VPAD_BUTTON_B) {
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(message) / 2, SCREEN_HEIGHT / 2 - 24, message, true);
|
f = fopen(UPDATE_SKIP_PATH, "w");
|
||||||
message = "Your system might not be blocking updates properly!";
|
if (f) {
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(message) / 2, SCREEN_HEIGHT / 2 + 0, message, true);
|
// It's **really** important to have this text on the stack.
|
||||||
message = "See https://wiiu.hacks.guide/#/block-updates for more information.";
|
// If it's read from the .rodata section the fwrite will softlock the console because the OSEffectiveToPhysical returns NULL for
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(message) / 2, SCREEN_HEIGHT / 2 + 24, message, true);
|
// everything between 0x00800000 - 0x01000000 at this stage.
|
||||||
|
const char text[] = "If this file exists, the Autoboot Module will not warn you about not blocking updates";
|
||||||
// draw bottom bar
|
fputs(text, f);
|
||||||
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_WHITE);
|
fclose(f);
|
||||||
DrawUtils::setFontSize(18);
|
}
|
||||||
const char *exitHints = "\ue000 Continue / \ue001 Don't show this again";
|
break;
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(exitHints) / 2, SCREEN_HEIGHT - 8, exitHints, true);
|
|
||||||
|
|
||||||
DrawUtils::endDraw();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
InputUtils::InputData buttons = InputUtils::getControllerInput();
|
|
||||||
|
|
||||||
if (buttons.trigger & VPAD_BUTTON_A) {
|
|
||||||
break;
|
|
||||||
} 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.
|
|
||||||
// If it's read from the .rodata section the fwrite will softlock the console because the OSEffectiveToPhysical returns NULL for
|
|
||||||
// everything between 0x00800000 - 0x01000000 at this stage.
|
|
||||||
const char text[] = "If this file exists, the Autoboot Module will not warn you about not blocking updates";
|
|
||||||
fputs(text, f);
|
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawUtils::beginDraw();
|
||||||
DrawUtils::clear(COLOR_BLACK);
|
DrawUtils::clear(COLOR_BLACK);
|
||||||
DrawUtils::endDraw();
|
DrawUtils::endDraw();
|
||||||
|
|
||||||
@ -410,6 +426,32 @@ void handleUpdateWarningScreen() {
|
|||||||
free(screenBuffer);
|
free(screenBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawDiscInsert(bool wrongDiscInserted) {
|
||||||
|
DrawUtils::beginDraw();
|
||||||
|
DrawUtils::clear(COLOR_BACKGROUND);
|
||||||
|
DrawUtils::setFontColor(COLOR_TEXT);
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(48);
|
||||||
|
|
||||||
|
if (wrongDiscInserted) {
|
||||||
|
const char *title = "The disc inserted into the console";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 40 + 48 + 8, title, true);
|
||||||
|
title = "is for a different software title.";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 40 + 2 * 48 + 8, title, true);
|
||||||
|
title = "Please change the disc.";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 40 + 4 * 48 + 8, title, true);
|
||||||
|
} else {
|
||||||
|
const char *title = "Please insert a disc.";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 40 + 48 + 8, title, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(18);
|
||||||
|
const char *exitHints = "\ue000 Launch Wii U Menu";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(exitHints) / 2, SCREEN_HEIGHT - 8, exitHints, true);
|
||||||
|
|
||||||
|
DrawUtils::endDraw();
|
||||||
|
}
|
||||||
|
|
||||||
bool handleDiscInsertScreen(uint64_t expectedTitleId, uint64_t *titleIdToLaunch) {
|
bool handleDiscInsertScreen(uint64_t expectedTitleId, uint64_t *titleIdToLaunch) {
|
||||||
if (titleIdToLaunch == nullptr) {
|
if (titleIdToLaunch == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("titleIdToLaunch is NULL");
|
DEBUG_FUNCTION_LINE_ERR("titleIdToLaunch is NULL");
|
||||||
@ -458,56 +500,43 @@ bool handleDiscInsertScreen(uint64_t expectedTitleId, uint64_t *titleIdToLaunch)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawUtils::beginDraw();
|
|
||||||
DrawUtils::clear(COLOR_BACKGROUND);
|
|
||||||
DrawUtils::setFontColor(COLOR_TEXT);
|
|
||||||
|
|
||||||
DrawUtils::setFontSize(48);
|
|
||||||
|
|
||||||
if (wrongDiscInserted) {
|
|
||||||
const char *title = "The disc inserted into the console";
|
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 40 + 48 + 8, title, true);
|
|
||||||
title = "is for a different software title.";
|
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 40 + 2 * 48 + 8, title, true);
|
|
||||||
title = "Please change the disc.";
|
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 40 + 4 * 48 + 8, title, true);
|
|
||||||
} else {
|
|
||||||
const char *title = "Please insert a disc.";
|
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(title) / 2, 40 + 48 + 8, title, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawUtils::setFontSize(18);
|
|
||||||
const char *exitHints = "\ue000 Launch Wii U Menu";
|
|
||||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(exitHints) / 2, SCREEN_HEIGHT - 8, exitHints, true);
|
|
||||||
|
|
||||||
DrawUtils::endDraw();
|
|
||||||
|
|
||||||
// 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) {
|
{
|
||||||
InputUtils::InputData buttons = InputUtils::getControllerInput();
|
PairMenu pairMenu;
|
||||||
|
|
||||||
if (buttons.trigger & VPAD_BUTTON_A) {
|
while (true) {
|
||||||
result = false;
|
if (pairMenu.ProcessPairScreen()) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetTitleIdOfDisc(&titleIdOfDisc, &discInserted)) {
|
drawDiscInsert(wrongDiscInserted);
|
||||||
if (discInserted) {
|
|
||||||
if (!allowDisc) {
|
InputUtils::InputData input = InputUtils::getControllerInput();
|
||||||
continue;
|
if (input.trigger & VPAD_BUTTON_A) {
|
||||||
}
|
result = false;
|
||||||
*titleIdToLaunch = titleIdOfDisc;
|
|
||||||
DEBUG_FUNCTION_LINE("Disc inserted! %016llX", titleIdOfDisc);
|
|
||||||
result = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
allowDisc = true;
|
|
||||||
|
if (GetTitleIdOfDisc(&titleIdOfDisc, &discInserted)) {
|
||||||
|
if (discInserted) {
|
||||||
|
if (!allowDisc) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*titleIdToLaunch = titleIdOfDisc;
|
||||||
|
DEBUG_FUNCTION_LINE("Disc inserted! %016llX", titleIdOfDisc);
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allowDisc = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawUtils::beginDraw();
|
||||||
DrawUtils::clear(COLOR_BLACK);
|
DrawUtils::clear(COLOR_BLACK);
|
||||||
DrawUtils::endDraw();
|
DrawUtils::endDraw();
|
||||||
|
|
||||||
|
241
source/PairUtils.cpp
Normal file
241
source/PairUtils.cpp
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
#include "PairUtils.h"
|
||||||
|
#include "DrawUtils.h"
|
||||||
|
#include "InputUtils.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include <coreinit/cache.h>
|
||||||
|
#include <coreinit/thread.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <nn/ccr/sys.h>
|
||||||
|
#include <padscore/kpad.h>
|
||||||
|
#include <padscore/wpad.h>
|
||||||
|
#include <vpad/input.h>
|
||||||
|
|
||||||
|
void PairMenu::drawPairKPADScreen() const {
|
||||||
|
DrawUtils::beginDraw();
|
||||||
|
DrawUtils::clear(COLOR_BACKGROUND);
|
||||||
|
|
||||||
|
DrawUtils::setFontColor(COLOR_TEXT);
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(26);
|
||||||
|
|
||||||
|
std::string textLine1 = "Press the SYNC Button on the controller you want to pair.";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(textLine1.c_str()) / 2, 40, textLine1.c_str(), true);
|
||||||
|
|
||||||
|
|
||||||
|
WPADExtensionType ext{};
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
bool isConnected = WPADProbe((WPADChan) i, &ext) == 0;
|
||||||
|
std::string textLine = string_format("Slot %d: ", i + 1);
|
||||||
|
if (isConnected) {
|
||||||
|
textLine += ext == WPAD_EXT_PRO_CONTROLLER ? "Pro Controller" : "Wiimote";
|
||||||
|
} else {
|
||||||
|
textLine += "No controller";
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawUtils::print(300, 140 + (i * 30), textLine.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(26);
|
||||||
|
|
||||||
|
std::string gamepadSyncText1 = "If you are pairing a Wii U GamePad, press the SYNC Button";
|
||||||
|
std::string gamepadSyncText2 = "on your Wii U console one more time";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(gamepadSyncText1.c_str()) / 2, SCREEN_HEIGHT - 100, gamepadSyncText1.c_str(), true);
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(gamepadSyncText2.c_str()) / 2, SCREEN_HEIGHT - 70, gamepadSyncText2.c_str(), true);
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(16);
|
||||||
|
|
||||||
|
const char *exitHints = "Press \ue001 to return";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(exitHints) / 2, SCREEN_HEIGHT - 8, exitHints, true);
|
||||||
|
|
||||||
|
DrawUtils::endDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PairMenu::drawPairScreen() const {
|
||||||
|
DrawUtils::beginDraw();
|
||||||
|
DrawUtils::clear(COLOR_BACKGROUND);
|
||||||
|
|
||||||
|
DrawUtils::setFontColor(COLOR_TEXT);
|
||||||
|
|
||||||
|
// Convert the pin to symbols and set the text
|
||||||
|
static char pinSymbols[][4] = {
|
||||||
|
"\u2660",
|
||||||
|
"\u2665",
|
||||||
|
"\u2666",
|
||||||
|
"\u2663"};
|
||||||
|
|
||||||
|
uint32_t pincode = mGamePadPincode;
|
||||||
|
|
||||||
|
std::string pin = std::string(pinSymbols[(pincode / 1000) % 10]) +
|
||||||
|
pinSymbols[(pincode / 100) % 10] +
|
||||||
|
pinSymbols[(pincode / 10) % 10] +
|
||||||
|
pinSymbols[pincode % 10];
|
||||||
|
|
||||||
|
std::string textLine1 = "Press the SYNC Button on the Wii U GamePad,";
|
||||||
|
std::string textLine2 = "and enter the four symbols shown below.";
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(26);
|
||||||
|
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(textLine1.c_str()) / 2, 60, textLine1.c_str(), true);
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(textLine2.c_str()) / 2, 100, textLine2.c_str(), true);
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(100);
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(pin.c_str()) / 2, (SCREEN_HEIGHT / 2) + 40, pin.c_str(), true);
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(20);
|
||||||
|
|
||||||
|
std::string textLine3 = string_format("(%d seconds remaining) ", mGamePadSyncTimeout - (uint32_t) (OSTicksToSeconds(OSGetTime() - mSyncGamePadStartTime)));
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(textLine3.c_str()) / 2, SCREEN_HEIGHT - 80, textLine3.c_str(), true);
|
||||||
|
|
||||||
|
DrawUtils::setFontSize(26);
|
||||||
|
|
||||||
|
std::string textLine4 = "Press the SYNC Button on the Wii U console to exit.";
|
||||||
|
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(textLine4.c_str()) / 2, SCREEN_HEIGHT - 40, textLine4.c_str(), true);
|
||||||
|
|
||||||
|
DrawUtils::endDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
PairMenu::PairMenu() {
|
||||||
|
CCRSysInit();
|
||||||
|
|
||||||
|
mState = STATE_WAIT;
|
||||||
|
mGamePadSyncTimeout = 120;
|
||||||
|
|
||||||
|
// Initialize IM
|
||||||
|
mIMHandle = IM_Open();
|
||||||
|
if (mIMHandle < 0) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("PairMenu: IM_Open failed");
|
||||||
|
OSFatal("PairMenu: IM_Open failed");
|
||||||
|
}
|
||||||
|
mIMRequest = (IMRequest *) memalign(0x40, sizeof(IMRequest));
|
||||||
|
|
||||||
|
// Allocate a separate request for IM_CancelGetEventNotify to avoid conflict with the pending IM_GetEventNotify request
|
||||||
|
mIMCancelRequest = (IMRequest *) memalign(0x40, sizeof(IMRequest));
|
||||||
|
|
||||||
|
if (!mIMRequest || !mIMCancelRequest) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to allocate im request");
|
||||||
|
OSFatal("PairMenu: Failed to allocate im request");
|
||||||
|
}
|
||||||
|
|
||||||
|
mIMEventMask = IM_EVENT_SYNC;
|
||||||
|
|
||||||
|
// Notify about sync button events
|
||||||
|
IM_GetEventNotify(mIMHandle, mIMRequest, &mIMEventMask, PairMenu::SyncButtonCallback, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PairMenu::~PairMenu() {
|
||||||
|
// Close IM
|
||||||
|
IM_CancelGetEventNotify(mIMHandle, mIMCancelRequest, nullptr, nullptr);
|
||||||
|
IM_Close(mIMHandle);
|
||||||
|
if (mIMCancelRequest) {
|
||||||
|
free(mIMCancelRequest);
|
||||||
|
mIMCancelRequest = {};
|
||||||
|
}
|
||||||
|
if (mIMRequest) {
|
||||||
|
free(mIMRequest);
|
||||||
|
mIMRequest = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deinit CCRSys
|
||||||
|
CCRSysExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" bool WPADStartSyncDevice();
|
||||||
|
|
||||||
|
bool PairMenu::ProcessPairScreen() {
|
||||||
|
switch (mState) {
|
||||||
|
case STATE_SYNC_WPAD: {
|
||||||
|
// WPAD syncing stops after ~18 seconds, make sure to restart it.
|
||||||
|
if ((uint32_t) OSTicksToSeconds(OSGetTime() - mSyncWPADStartTime) >= 18) {
|
||||||
|
WPADStartSyncDevice();
|
||||||
|
mSyncWPADStartTime = OSGetTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
InputUtils::InputData input = InputUtils::getControllerInput();
|
||||||
|
|
||||||
|
// Stop syncing when pressing A or B.
|
||||||
|
if (input.trigger & (VPAD_BUTTON_A | VPAD_BUTTON_B)) {
|
||||||
|
mState = STATE_WAIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATE_SYNC_GAMEPAD: {
|
||||||
|
if (CCRSysGetPincode(&mGamePadPincode) != 0) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("CCRSysGetPincode failed");
|
||||||
|
mState = STATE_WAIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start pairing to slot 1 (second gamepad)
|
||||||
|
if (CCRSysStartPairing(0, mGamePadSyncTimeout) != 0) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("CCRSysStartPairing failed.");
|
||||||
|
mState = STATE_WAIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pairing has started, save start time
|
||||||
|
mSyncGamePadStartTime = OSGetTime();
|
||||||
|
mState = STATE_PAIRING;
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("Started GamePad syncing.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATE_PAIRING: {
|
||||||
|
// Get the current pairing state
|
||||||
|
CCRSysPairingState pairingState = CCRSysGetPairingState();
|
||||||
|
if (pairingState == CCR_SYS_PAIRING_TIMED_OUT) {
|
||||||
|
DEBUG_FUNCTION_LINE("GamePad SYNC timed out.");
|
||||||
|
// Pairing has timed out or was cancelled
|
||||||
|
CCRSysStopPairing();
|
||||||
|
mState = STATE_WAIT;
|
||||||
|
} else if (pairingState == CCR_SYS_PAIRING_FINISHED) {
|
||||||
|
DEBUG_FUNCTION_LINE("GamePad paired.");
|
||||||
|
mState = STATE_WAIT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATE_CANCEL: {
|
||||||
|
CCRSysStopPairing();
|
||||||
|
mState = STATE_WAIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATE_WAIT:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (mState) {
|
||||||
|
case STATE_WAIT: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case STATE_SYNC_WPAD:
|
||||||
|
drawPairKPADScreen();
|
||||||
|
break;
|
||||||
|
case STATE_SYNC_GAMEPAD:
|
||||||
|
case STATE_PAIRING:
|
||||||
|
case STATE_CANCEL: {
|
||||||
|
drawPairScreen();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PairMenu::SyncButtonCallback(IOSError error, void *arg) {
|
||||||
|
auto *pairMenu = (PairMenu *) arg;
|
||||||
|
|
||||||
|
if (error == IOS_ERROR_OK && pairMenu && (pairMenu->mIMEventMask & IM_EVENT_SYNC)) {
|
||||||
|
if (pairMenu->mState == STATE_WAIT) {
|
||||||
|
pairMenu->mState = STATE_SYNC_WPAD;
|
||||||
|
// We need to restart the WPAD pairing every 18 seconds. For the timing we need to save the current time.
|
||||||
|
pairMenu->mSyncWPADStartTime = OSGetTime();
|
||||||
|
} else if (pairMenu->mState == STATE_SYNC_WPAD) {
|
||||||
|
pairMenu->mState = STATE_SYNC_GAMEPAD;
|
||||||
|
} else if (pairMenu->mState == STATE_SYNC_GAMEPAD || pairMenu->mState == STATE_PAIRING) {
|
||||||
|
pairMenu->mState = STATE_CANCEL;
|
||||||
|
}
|
||||||
|
OSMemoryBarrier();
|
||||||
|
IM_GetEventNotify(pairMenu->mIMHandle, pairMenu->mIMRequest, &pairMenu->mIMEventMask, PairMenu::SyncButtonCallback, pairMenu);
|
||||||
|
}
|
||||||
|
}
|
45
source/PairUtils.h
Normal file
45
source/PairUtils.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MenuUtils.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include <coreinit/cache.h>
|
||||||
|
#include <coreinit/im.h>
|
||||||
|
#include <coreinit/ios.h>
|
||||||
|
#include <coreinit/time.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <nn/ccr/sys.h>
|
||||||
|
|
||||||
|
|
||||||
|
class PairMenu {
|
||||||
|
public:
|
||||||
|
PairMenu();
|
||||||
|
|
||||||
|
~PairMenu();
|
||||||
|
|
||||||
|
bool ProcessPairScreen();
|
||||||
|
|
||||||
|
static void SyncButtonCallback(IOSError error, void *arg);
|
||||||
|
|
||||||
|
void drawPairScreen() const;
|
||||||
|
|
||||||
|
void drawPairKPADScreen() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum PairMenuState {
|
||||||
|
STATE_WAIT, // Wait for SYNC button press
|
||||||
|
STATE_SYNC_WPAD,
|
||||||
|
STATE_SYNC_GAMEPAD,
|
||||||
|
STATE_PAIRING,
|
||||||
|
STATE_CANCEL,
|
||||||
|
};
|
||||||
|
|
||||||
|
IOSHandle mIMHandle{};
|
||||||
|
IMRequest *mIMRequest{};
|
||||||
|
IMRequest *mIMCancelRequest{};
|
||||||
|
OSTime mSyncWPADStartTime = 0;
|
||||||
|
OSTime mSyncGamePadStartTime = 0;
|
||||||
|
uint32_t mGamePadPincode = 0;
|
||||||
|
PairMenuState mState = STATE_WAIT;
|
||||||
|
uint32_t mGamePadSyncTimeout = 120;
|
||||||
|
IMEventMask mIMEventMask{};
|
||||||
|
};
|
@ -10,7 +10,6 @@
|
|||||||
#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>
|
||||||
@ -51,6 +50,8 @@ int32_t main(int32_t argc, char **argv) {
|
|||||||
OSFatal("AutobootModule: Mocha_InitLibrary failed");
|
OSFatal("AutobootModule: Mocha_InitLibrary failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputUtils::InputData buttons = InputUtils::getControllerInput();
|
||||||
|
|
||||||
FSAInit();
|
FSAInit();
|
||||||
auto client = FSAAddClient(nullptr);
|
auto client = FSAAddClient(nullptr);
|
||||||
if (client > 0) {
|
if (client > 0) {
|
||||||
@ -70,8 +71,6 @@ 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";
|
||||||
@ -135,7 +134,6 @@ int32_t main(int32_t argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InputUtils::DeInit();
|
InputUtils::DeInit();
|
||||||
|
|
||||||
Mocha_DeInitLibrary();
|
Mocha_DeInitLibrary();
|
||||||
deinitLogging();
|
deinitLogging();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user