Fix input when no gamepad is connected.

This commit is contained in:
Maschell 2021-10-17 15:26:25 +02:00
parent 6f833c9811
commit 80110c3f4c
17 changed files with 453 additions and 429 deletions

View File

@ -1,6 +1,6 @@
FROM wiiuenv/devkitppc:20210917 FROM wiiuenv/devkitppc:20210920
COPY --from=wiiuenv/libiosuhax:20210109 /artifacts $DEVKITPRO COPY --from=wiiuenv/libiosuhax:20211008 /artifacts $DEVKITPRO
COPY --from=wiiuenv/devkitarm:20210917 $DEVKITPRO/devkitARM $DEVKITPRO/devkitARM COPY --from=wiiuenv/devkitarm:20210917 $DEVKITPRO/devkitARM $DEVKITPRO/devkitARM
ENV DEVKITARM=/opt/devkitpro/devkitARM ENV DEVKITARM=/opt/devkitpro/devkitARM

View File

@ -35,12 +35,10 @@ BUILD := build
SOURCES := source \ SOURCES := source \
source/common \ source/common \
source/utils \ source/utils \
source/fs source/fs \
source/input
INCLUDES := include source INCLUDES := include source
CONTENT := meta
ICON := meta/icon.jpg ICON := meta/icon.jpg
TV_SPLASH := meta/icon.jpg
DRC_SPLASH := meta/icon.jpg
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# options for code generation # options for code generation

View File

@ -1,7 +1,7 @@
#include "ApplicationState.h" #include "ApplicationState.h"
#include "WiiUScreen.h" #include "utils/WiiUScreen.h"
#include "ScreenUtils.h" #include "utils/ScreenUtils.h"
#include "StringTools.h" #include "utils/StringTools.h"
#include "../build/safe_payload.h" #include "../build/safe_payload.h"
#include <sysapp/launch.h> #include <sysapp/launch.h>
#include <iosuhax.h> #include <iosuhax.h>

View File

@ -2,9 +2,9 @@
#include <string> #include <string>
#include <optional> #include <optional>
#include <input/Input.h>
#include "common/common.h" #include "common/common.h"
#include "InstallerService.h" #include "InstallerService.h"
#include "Input.h"
#include "Menu.h" #include "Menu.h"
class ApplicationState { class ApplicationState {

View File

@ -1,7 +1,7 @@
#include "common/common.h" #include "common/common.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "WiiUScreen.h" #include "utils/WiiUScreen.h"
#include "StringTools.h" #include "utils/StringTools.h"
#include "fs/FSUtils.h" #include "fs/FSUtils.h"
#include "common/fst_structs.h" #include "common/fst_structs.h"
#include "InstallerService.h" #include "InstallerService.h"

View File

@ -4,10 +4,8 @@
#include <functional> #include <functional>
#include <utility> #include <utility>
#include <list> #include <list>
#include "Input.h" #include "utils/WiiUScreen.h"
#include "WiiUScreen.h" #include "utils/ScreenUtils.h"
#include "ScreenUtils.h"
#include "VPADInput.h"
template <typename T> template <typename T>
class Menu { class Menu {

View File

@ -0,0 +1,20 @@
#pragma once
class CombinedInput : public Input {
public:
void combine(const Input &b) {
data.buttons_h |= b.data.buttons_h;
}
void process() {
data.buttons_d |= (data.buttons_h & (~lastData.buttons_h));
data.buttons_r |= (lastData.buttons_h & (~data.buttons_h));
lastData.buttons_h = data.buttons_h;
}
void reset() {
data.buttons_h = 0;
data.buttons_d = 0;
data.buttons_r = 0;
}
};

View File

@ -1,66 +1,61 @@
#pragma once #pragma once
#include <cstring> #include <cstring>
#include <cstdint> #include <cstdint>
class Input { class Input {
public: public:
//!Constructor //!Constructor
Input() = default; Input() = default;
//!Destructor //!Destructor
virtual ~Input() = default; virtual ~Input() = default;
void combine(const Input& b) { enum eButtons {
data.buttons_d |= b.data.buttons_d; BUTTON_NONE = 0x0000,
data.buttons_h |= b.data.buttons_h; VPAD_TOUCH = 0x80000000,
data.buttons_r |= b.data.buttons_r; BUTTON_Z = 0x20000,
} BUTTON_C = 0x10000,
BUTTON_A = 0x8000,
enum eButtons { BUTTON_B = 0x4000,
BUTTON_NONE = 0x0000, BUTTON_X = 0x2000,
VPAD_TOUCH = 0x80000000, BUTTON_Y = 0x1000,
BUTTON_Z = 0x20000, BUTTON_1 = BUTTON_Y,
BUTTON_C = 0x10000, BUTTON_2 = BUTTON_X,
BUTTON_A = 0x8000, BUTTON_LEFT = 0x0800,
BUTTON_B = 0x4000, BUTTON_RIGHT = 0x0400,
BUTTON_X = 0x2000, BUTTON_UP = 0x0200,
BUTTON_Y = 0x1000, BUTTON_DOWN = 0x0100,
BUTTON_1 = BUTTON_Y, BUTTON_ZL = 0x0080,
BUTTON_2 = BUTTON_X, BUTTON_ZR = 0x0040,
BUTTON_LEFT = 0x0800, BUTTON_L = 0x0020,
BUTTON_RIGHT = 0x0400, BUTTON_R = 0x0010,
BUTTON_UP = 0x0200, BUTTON_PLUS = 0x0008,
BUTTON_DOWN = 0x0100, BUTTON_MINUS = 0x0004,
BUTTON_ZL = 0x0080, BUTTON_HOME = 0x0002,
BUTTON_ZR = 0x0040, BUTTON_SYNC = 0x0001,
BUTTON_L = 0x0020, STICK_R_LEFT = 0x04000000,
BUTTON_R = 0x0010, STICK_R_RIGHT = 0x02000000,
BUTTON_PLUS = 0x0008, STICK_R_UP = 0x01000000,
BUTTON_MINUS = 0x0004, STICK_R_DOWN = 0x00800000,
BUTTON_HOME = 0x0002, STICK_L_LEFT = 0x40000000,
BUTTON_SYNC = 0x0001, STICK_L_RIGHT = 0x20000000,
STICK_R_LEFT = 0x04000000, STICK_L_UP = 0x10000000,
STICK_R_RIGHT = 0x02000000, STICK_L_DOWN = 0x08000000
STICK_R_UP = 0x01000000, };
STICK_R_DOWN = 0x00800000,
STICK_L_LEFT = 0x40000000, typedef struct {
STICK_L_RIGHT = 0x20000000, uint32_t buttons_h;
STICK_L_UP = 0x10000000, uint32_t buttons_d;
STICK_L_DOWN = 0x08000000 uint32_t buttons_r;
}; bool validPointer;
bool touched;
typedef struct { float pointerAngle;
uint32_t buttons_h; int32_t x;
uint32_t buttons_d; int32_t y;
uint32_t buttons_r; } PadData;
bool validPointer;
bool touched; PadData data{};
float pointerAngle; PadData lastData{};
int32_t x;
int32_t y; };
} PadData;
PadData data{};
PadData lastData{};
};

View File

@ -1,58 +1,61 @@
#pragma once #pragma once
/**************************************************************************** /****************************************************************************
* Copyright (C) 2015 Dimok * Copyright (C) 2015 Dimok
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/ ****************************************************************************/
#include <vpad/input.h> #include <vpad/input.h>
#include "Input.h" #include "Input.h"
class VPadInput : public Input { class VPadInput : public Input {
public: public:
//!Constructor //!Constructor
VPadInput() { VPadInput() {
} memset(&vpad, 0, sizeof(vpad));
}
//!Destructor
~VPadInput() override {} //!Destructor
~VPadInput() override = default;
bool update(int32_t width, int32_t height) {
lastData = data; bool update(int32_t width, int32_t height) {
lastData = data;
VPADReadError vpadError = VPAD_READ_NO_SAMPLES;
VPADRead(VPAD_CHAN_0, &vpad, 1, &vpadError); VPADReadError vpadError = VPAD_READ_NO_SAMPLES;
VPADRead(VPAD_CHAN_0, &vpad, 1, &vpadError);
if (vpadError == VPAD_READ_SUCCESS) {
data.buttons_r = vpad.release; if (vpadError == VPAD_READ_SUCCESS) {
data.buttons_h = vpad.hold; data.buttons_r = vpad.release;
data.buttons_d = vpad.trigger; data.buttons_h = vpad.hold;
data.validPointer = !vpad.tpNormal.validity; data.buttons_d = vpad.trigger;
data.touched = vpad.tpNormal.touched; data.validPointer = !vpad.tpNormal.validity;
data.touched = vpad.tpNormal.touched;
VPADGetTPCalibratedPoint(VPAD_CHAN_0, &tpCalib, &vpad.tpFiltered1);
VPADGetTPCalibratedPoint(VPAD_CHAN_0, &tpCalib, &vpad.tpFiltered1);
//! calculate the screen offsets
data.x = -(width >> 1) + (int32_t) (((float) tpCalib.x / 1280.0f) * (float) width); //! calculate the screen offsets
data.y = -(height >> 1) + (int32_t) (float) height - (((float) tpCalib.y / 720.0f) * (float) height); data.x = -(width >> 1) + (int32_t) (((float) tpCalib.x / 1280.0f) * (float) width);
data.y = -(height >> 1) + (int32_t) (float) height - (((float) tpCalib.y / 720.0f) * (float) height);
return true;
} return true;
return false; } else {
} data.buttons_h = 0;
}
private: return false;
VPADStatus vpad{}; }
VPADTouchData tpCalib{};
private:
VPADStatus vpad{};
VPADTouchData tpCalib{};
}; };

View File

@ -31,43 +31,43 @@ public:
uint32_t remapWiiMoteButtons(uint32_t buttons) { uint32_t remapWiiMoteButtons(uint32_t buttons) {
uint32_t conv_buttons = 0; uint32_t conv_buttons = 0;
if(buttons & WPAD_BUTTON_LEFT) if (buttons & WPAD_BUTTON_LEFT)
conv_buttons |= Input::BUTTON_LEFT; conv_buttons |= Input::BUTTON_LEFT;
if(buttons & WPAD_BUTTON_RIGHT) if (buttons & WPAD_BUTTON_RIGHT)
conv_buttons |= Input::BUTTON_RIGHT; conv_buttons |= Input::BUTTON_RIGHT;
if(buttons & WPAD_BUTTON_DOWN) if (buttons & WPAD_BUTTON_DOWN)
conv_buttons |= Input::BUTTON_DOWN; conv_buttons |= Input::BUTTON_DOWN;
if(buttons & WPAD_BUTTON_UP) if (buttons & WPAD_BUTTON_UP)
conv_buttons |= Input::BUTTON_UP; conv_buttons |= Input::BUTTON_UP;
if(buttons & WPAD_BUTTON_PLUS) if (buttons & WPAD_BUTTON_PLUS)
conv_buttons |= Input::BUTTON_PLUS; conv_buttons |= Input::BUTTON_PLUS;
if(buttons & WPAD_BUTTON_2) if (buttons & WPAD_BUTTON_2)
conv_buttons |= Input::BUTTON_2; conv_buttons |= Input::BUTTON_2;
if(buttons & WPAD_BUTTON_1) if (buttons & WPAD_BUTTON_1)
conv_buttons |= Input::BUTTON_1; conv_buttons |= Input::BUTTON_1;
if(buttons & WPAD_BUTTON_B) if (buttons & WPAD_BUTTON_B)
conv_buttons |= Input::BUTTON_B; conv_buttons |= Input::BUTTON_B;
if(buttons & WPAD_BUTTON_A) if (buttons & WPAD_BUTTON_A)
conv_buttons |= Input::BUTTON_A; conv_buttons |= Input::BUTTON_A;
if(buttons & WPAD_BUTTON_MINUS) if (buttons & WPAD_BUTTON_MINUS)
conv_buttons |= Input::BUTTON_MINUS; conv_buttons |= Input::BUTTON_MINUS;
if(buttons & WPAD_BUTTON_Z) if (buttons & WPAD_BUTTON_Z)
conv_buttons |= Input::BUTTON_Z; conv_buttons |= Input::BUTTON_Z;
if(buttons & WPAD_BUTTON_C) if (buttons & WPAD_BUTTON_C)
conv_buttons |= Input::BUTTON_C; conv_buttons |= Input::BUTTON_C;
if(buttons & WPAD_BUTTON_HOME) if (buttons & WPAD_BUTTON_HOME)
conv_buttons |= Input::BUTTON_HOME; conv_buttons |= Input::BUTTON_HOME;
return conv_buttons; return conv_buttons;
@ -76,63 +76,65 @@ public:
uint32_t remapClassicButtons(uint32_t buttons) { uint32_t remapClassicButtons(uint32_t buttons) {
uint32_t conv_buttons = 0; uint32_t conv_buttons = 0;
if(buttons & WPAD_CLASSIC_BUTTON_LEFT) if (buttons & WPAD_CLASSIC_BUTTON_LEFT)
conv_buttons |= Input::BUTTON_LEFT; conv_buttons |= Input::BUTTON_LEFT;
if(buttons & WPAD_CLASSIC_BUTTON_RIGHT) if (buttons & WPAD_CLASSIC_BUTTON_RIGHT)
conv_buttons |= Input::BUTTON_RIGHT; conv_buttons |= Input::BUTTON_RIGHT;
if(buttons & WPAD_CLASSIC_BUTTON_DOWN) if (buttons & WPAD_CLASSIC_BUTTON_DOWN)
conv_buttons |= Input::BUTTON_DOWN; conv_buttons |= Input::BUTTON_DOWN;
if(buttons & WPAD_CLASSIC_BUTTON_UP) if (buttons & WPAD_CLASSIC_BUTTON_UP)
conv_buttons |= Input::BUTTON_UP; conv_buttons |= Input::BUTTON_UP;
if(buttons & WPAD_CLASSIC_BUTTON_PLUS) if (buttons & WPAD_CLASSIC_BUTTON_PLUS)
conv_buttons |= Input::BUTTON_PLUS; conv_buttons |= Input::BUTTON_PLUS;
if(buttons & WPAD_CLASSIC_BUTTON_X) if (buttons & WPAD_CLASSIC_BUTTON_X)
conv_buttons |= Input::BUTTON_X; conv_buttons |= Input::BUTTON_X;
if(buttons & WPAD_CLASSIC_BUTTON_Y) if (buttons & WPAD_CLASSIC_BUTTON_Y)
conv_buttons |= Input::BUTTON_Y; conv_buttons |= Input::BUTTON_Y;
if(buttons & WPAD_CLASSIC_BUTTON_B) if (buttons & WPAD_CLASSIC_BUTTON_B)
conv_buttons |= Input::BUTTON_B; conv_buttons |= Input::BUTTON_B;
if(buttons & WPAD_CLASSIC_BUTTON_A) if (buttons & WPAD_CLASSIC_BUTTON_A)
conv_buttons |= Input::BUTTON_A; conv_buttons |= Input::BUTTON_A;
if(buttons & WPAD_CLASSIC_BUTTON_MINUS) if (buttons & WPAD_CLASSIC_BUTTON_MINUS)
conv_buttons |= Input::BUTTON_MINUS; conv_buttons |= Input::BUTTON_MINUS;
if(buttons & WPAD_CLASSIC_BUTTON_HOME) if (buttons & WPAD_CLASSIC_BUTTON_HOME)
conv_buttons |= Input::BUTTON_HOME; conv_buttons |= Input::BUTTON_HOME;
if(buttons & WPAD_CLASSIC_BUTTON_ZR) if (buttons & WPAD_CLASSIC_BUTTON_ZR)
conv_buttons |= Input::BUTTON_ZR; conv_buttons |= Input::BUTTON_ZR;
if(buttons & WPAD_CLASSIC_BUTTON_ZL) if (buttons & WPAD_CLASSIC_BUTTON_ZL)
conv_buttons |= Input::BUTTON_ZL; conv_buttons |= Input::BUTTON_ZL;
if(buttons & WPAD_CLASSIC_BUTTON_R) if (buttons & WPAD_CLASSIC_BUTTON_R)
conv_buttons |= Input::BUTTON_R; conv_buttons |= Input::BUTTON_R;
if(buttons & WPAD_CLASSIC_BUTTON_L) if (buttons & WPAD_CLASSIC_BUTTON_L)
conv_buttons |= Input::BUTTON_L; conv_buttons |= Input::BUTTON_L;
return conv_buttons; return conv_buttons;
} }
bool update(int32_t width, int32_t height) { bool update(int32_t width, int32_t height) {
lastData = data;
WPADExtensionType type; WPADExtensionType type;
if (WPADProbe(channel, &type) != 0) { if (WPADProbe(channel, &type) != 0) {
data.buttons_h = 0;
return false; return false;
} }
KPADRead(channel, &kpad, 1); KPADRead(channel, &kpad, 1);
if(kpad.extensionType == WPAD_EXT_CORE || kpad.extensionType == WPAD_EXT_NUNCHUK) { if (kpad.extensionType == WPAD_EXT_CORE || kpad.extensionType == WPAD_EXT_NUNCHUK) {
data.buttons_r = remapWiiMoteButtons(kpad.release); data.buttons_r = remapWiiMoteButtons(kpad.release);
data.buttons_h = remapWiiMoteButtons(kpad.hold); data.buttons_h = remapWiiMoteButtons(kpad.hold);
data.buttons_d = remapWiiMoteButtons(kpad.trigger); data.buttons_d = remapWiiMoteButtons(kpad.trigger);
@ -147,11 +149,11 @@ public:
(kpad.pos.y >= -1.0f && kpad.pos.y <= 1.0f); (kpad.pos.y >= -1.0f && kpad.pos.y <= 1.0f);
//! calculate the screen offsets if pointer is valid else leave old value //! calculate the screen offsets if pointer is valid else leave old value
if(data.validPointer) { if (data.validPointer) {
data.x = (width >> 1) * kpad.pos.x; data.x = (width >> 1) * kpad.pos.x;
data.y = (height >> 1) * (-kpad.pos.y); data.y = (height >> 1) * (-kpad.pos.y);
if(kpad.angle.y > 0.0f) { if (kpad.angle.y > 0.0f) {
data.pointerAngle = (-kpad.angle.x + 1.0f) * 0.5f * 180.0f; data.pointerAngle = (-kpad.angle.x + 1.0f) * 0.5f * 180.0f;
} else { } else {
data.pointerAngle = (kpad.angle.x + 1.0f) * 0.5f * 180.0f - 180.0f; data.pointerAngle = (kpad.angle.x + 1.0f) * 0.5f * 180.0f - 180.0f;

View File

@ -7,18 +7,20 @@
#include <iosuhax.h> #include <iosuhax.h>
#include <iosuhax_devoptab.h> #include <iosuhax_devoptab.h>
#include <string_view> #include <string_view>
#include "WiiUScreen.h" #include <input/WPADInput.h>
#include <input/VPADInput.h>
#include <input/CombinedInput.h>
#include "utils/WiiUScreen.h"
#include "InstallerService.h" #include "InstallerService.h"
#include "ApplicationState.h" #include "ApplicationState.h"
#include "WPADInput.h"
#include "../build/safe_payload.h" #include "../build/safe_payload.h"
constexpr bool strings_equal(char const *a, char const *b) { constexpr bool strings_equal(char const *a, char const *b) {
return std::string_view(a) == b; return std::string_view(a) == b;
} }
static_assert(strings_equal(RPX_HASH, "cd4c1459d793a600d12afa33425f43be0cc5dfa3"), "Built with an untested root.rpx! Remove this check if you really know what you're doing."); static_assert(strings_equal(RPX_HASH, "1736574cf6c949557aed0c817eb1927e35a9b820"), "Built with an untested root.rpx! Remove this check if you really know what you're doing.");
void initIOSUHax(); void initIOSUHax();
@ -30,12 +32,13 @@ bool sIosuhaxMount = false;
int main_loop() { int main_loop() {
DEBUG_FUNCTION_LINE("Creating state"); DEBUG_FUNCTION_LINE("Creating state");
ApplicationState state; ApplicationState state;
CombinedInput baseInput;
VPadInput vpadInput; VPadInput vpadInput;
WPADInput wpadInputs[4] = { WPADInput wpadInputs[4] = {
WPAD_CHAN_0, WPAD_CHAN_0,
WPAD_CHAN_1, WPAD_CHAN_1,
WPAD_CHAN_2, WPAD_CHAN_2,
WPAD_CHAN_3 WPAD_CHAN_3
}; };
if (sFSAFd < 0 || !sIosuhaxMount) { if (sFSAFd < 0 || !sIosuhaxMount) {
@ -44,12 +47,17 @@ int main_loop() {
DEBUG_FUNCTION_LINE("Entering main loop"); DEBUG_FUNCTION_LINE("Entering main loop");
while (WHBProcIsRunning()) { while (WHBProcIsRunning()) {
vpadInput.update(1280, 720); baseInput.reset();
for (int i = 0; i < 4; i++) { if (vpadInput.update(1280, 720)) {
wpadInputs[i].update(1280, 720); baseInput.combine(vpadInput);
vpadInput.combine(wpadInputs[i]);
} }
state.update(&vpadInput); for (auto &wpadInput: wpadInputs) {
if (wpadInput.update(1280, 720)) {
baseInput.combine(wpadInput);
}
}
baseInput.process();
state.update(&baseInput);
state.render(); state.render();
} }

View File

@ -1,48 +1,48 @@
/**************************************************************************** /****************************************************************************
* Copyright (C) 2018 Maschell * Copyright (C) 2018 Maschell
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/ ****************************************************************************/
#include <coreinit/screen.h> #include <coreinit/screen.h>
#include "ScreenUtils.h" #include "ScreenUtils.h"
void ScreenUtils::printTextOnScreen(ConsoleScreenID screen, int x, int y, const char *msg) { void ScreenUtils::printTextOnScreen(ConsoleScreenID screen, int x, int y, const char *msg) {
if (!msg) { if (!msg) {
return; return;
} }
if (screen != CONSOLE_SCREEN_DRC) { // Draw TV if it's not DRC exclusive. if (screen != CONSOLE_SCREEN_DRC) { // Draw TV if it's not DRC exclusive.
OSScreenPutFontEx(SCREEN_TV, x, y, msg); OSScreenPutFontEx(SCREEN_TV, x, y, msg);
} }
if (screen != CONSOLE_SCREEN_TV) { // Draw DRC if it's not TV exclusive. if (screen != CONSOLE_SCREEN_TV) { // Draw DRC if it's not TV exclusive.
OSScreenPutFontEx(SCREEN_DRC, x, y, msg); OSScreenPutFontEx(SCREEN_DRC, x, y, msg);
} }
} }
void ScreenUtils::OSScreenClear(ConsoleScreenID screen, uint32_t color) { void ScreenUtils::OSScreenClear(ConsoleScreenID screen, uint32_t color) {
if (screen != CONSOLE_SCREEN_DRC) { // Clear TV if it's not DRC exclusive. if (screen != CONSOLE_SCREEN_DRC) { // Clear TV if it's not DRC exclusive.
OSScreenClearBufferEx(SCREEN_TV, color); OSScreenClearBufferEx(SCREEN_TV, color);
} }
if (screen != CONSOLE_SCREEN_TV) { // Clear DRC if it's not TV exclusive. if (screen != CONSOLE_SCREEN_TV) { // Clear DRC if it's not TV exclusive.
OSScreenClearBufferEx(SCREEN_DRC, color); OSScreenClearBufferEx(SCREEN_DRC, color);
} }
} }
void ScreenUtils::flipBuffers(ConsoleScreenID screen) { void ScreenUtils::flipBuffers(ConsoleScreenID screen) {
if (screen != CONSOLE_SCREEN_DRC) { // Flip TV buffer if it's not DRC exclusive. if (screen != CONSOLE_SCREEN_DRC) { // Flip TV buffer if it's not DRC exclusive.
OSScreenFlipBuffersEx(SCREEN_TV); OSScreenFlipBuffersEx(SCREEN_TV);
} }
if (screen != CONSOLE_SCREEN_TV) { // Flip DRC buffer if it's not TV exclusive. if (screen != CONSOLE_SCREEN_TV) { // Flip DRC buffer if it's not TV exclusive.
OSScreenFlipBuffersEx(SCREEN_DRC); OSScreenFlipBuffersEx(SCREEN_DRC);
} }
} }

View File

@ -1,55 +1,55 @@
/**************************************************************************** /****************************************************************************
* Copyright (C) 2018-2020 Maschell * Copyright (C) 2018-2020 Maschell
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/ ****************************************************************************/
#pragma once #pragma once
//! Defines the ID of a display usable with OSScreen. //! Defines the ID of a display usable with OSScreen.
typedef enum ConsoleScreenID { typedef enum ConsoleScreenID {
//! Represents the TV connected to the system. //! Represents the TV connected to the system.
CONSOLE_SCREEN_TV = 0, CONSOLE_SCREEN_TV = 0,
//! Represents the screen in the DRC (gamepad). //! Represents the screen in the DRC (gamepad).
CONSOLE_SCREEN_DRC = 1, CONSOLE_SCREEN_DRC = 1,
//! Represents both screens //! Represents both screens
CONSOLE_SCREEN_BOTH = 2, CONSOLE_SCREEN_BOTH = 2,
} ConsoleScreenID; } ConsoleScreenID;
class ScreenUtils { class ScreenUtils {
public: public:
/** /**
Clears the screen for the given screens Clears the screen for the given screens
\param screen defines on which screens should be printed \param screen defines on which screens should be printed
\param x defines the x position (character position) where the text should be printed \param x defines the x position (character position) where the text should be printed
\param y defines on which line the text should be printed \param y defines on which line the text should be printed
\param msg C string that contains the text to be printed. \param msg C string that contains the text to be printed.
**/ **/
static void printTextOnScreen(ConsoleScreenID screen, int x, int y, const char *msg); static void printTextOnScreen(ConsoleScreenID screen, int x, int y, const char *msg);
/** /**
Clears the screen for the given screens Clears the screen for the given screens
\param screen defines which screens should be cleared \param screen defines which screens should be cleared
**/ **/
static void OSScreenClear(ConsoleScreenID screen, uint32_t i); static void OSScreenClear(ConsoleScreenID screen, uint32_t i);
/** /**
Flips the buffer for the given screens Flips the buffer for the given screens
\param screen defines which screens should be flipped. \param screen defines which screens should be flipped.
**/ **/
static void flipBuffers(ConsoleScreenID screen); static void flipBuffers(ConsoleScreenID screen);
private: private:
ScreenUtils() = default; ScreenUtils() = default;
~ScreenUtils() = default; ~ScreenUtils() = default;
}; };

View File

@ -1,93 +1,93 @@
#include "WiiUScreen.h" #include "WiiUScreen.h"
#include "ScreenUtils.h" #include "ScreenUtils.h"
#include <coreinit/memdefaultheap.h> #include <coreinit/memdefaultheap.h>
#include <cstdarg> #include <cstdarg>
#include <cstdio> #include <cstdio>
void *WiiUScreen::sBufferTV = nullptr; void *WiiUScreen::sBufferTV = nullptr;
void *WiiUScreen::sBufferDRC = nullptr; void *WiiUScreen::sBufferDRC = nullptr;
uint32_t WiiUScreen::sBufferSizeTV = 0; uint32_t WiiUScreen::sBufferSizeTV = 0;
uint32_t WiiUScreen::sBufferSizeDRC = 0; uint32_t WiiUScreen::sBufferSizeDRC = 0;
bool WiiUScreen::sConsoleHasForeground = true; bool WiiUScreen::sConsoleHasForeground = true;
uint32_t WiiUScreen::consoleColor = 0x041F60FF; uint32_t WiiUScreen::consoleColor = 0x041F60FF;
uint32_t WiiUScreen::consoleCursorY = 0; uint32_t WiiUScreen::consoleCursorY = 0;
uint32_t WiiUScreen::ProcCallbackAcquired(void *context) { uint32_t WiiUScreen::ProcCallbackAcquired(void *context) {
MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
if (sBufferSizeTV) { if (sBufferSizeTV) {
sBufferTV = MEMAllocFromFrmHeapEx(heap, sBufferSizeTV, 4); sBufferTV = MEMAllocFromFrmHeapEx(heap, sBufferSizeTV, 4);
} }
if (sBufferSizeDRC) { if (sBufferSizeDRC) {
sBufferDRC = MEMAllocFromFrmHeapEx(heap, sBufferSizeDRC, 4); sBufferDRC = MEMAllocFromFrmHeapEx(heap, sBufferSizeDRC, 4);
} }
sConsoleHasForeground = true; sConsoleHasForeground = true;
OSScreenSetBufferEx(SCREEN_TV, sBufferTV); OSScreenSetBufferEx(SCREEN_TV, sBufferTV);
OSScreenSetBufferEx(SCREEN_DRC, sBufferDRC); OSScreenSetBufferEx(SCREEN_DRC, sBufferDRC);
return 0; return 0;
} }
uint32_t WiiUScreen::ProcCallbackReleased(void *context) { uint32_t WiiUScreen::ProcCallbackReleased(void *context) {
MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
MEMFreeByStateToFrmHeap(heap, CONSOLE_FRAME_HEAP_TAG); MEMFreeByStateToFrmHeap(heap, CONSOLE_FRAME_HEAP_TAG);
sConsoleHasForeground = FALSE; sConsoleHasForeground = FALSE;
return 0; return 0;
} }
bool WiiUScreen::Init() { bool WiiUScreen::Init() {
OSScreenInit(); OSScreenInit();
sBufferSizeTV = OSScreenGetBufferSizeEx(SCREEN_TV); sBufferSizeTV = OSScreenGetBufferSizeEx(SCREEN_TV);
sBufferSizeDRC = OSScreenGetBufferSizeEx(SCREEN_DRC); sBufferSizeDRC = OSScreenGetBufferSizeEx(SCREEN_DRC);
WiiUScreen::ProcCallbackAcquired(nullptr); WiiUScreen::ProcCallbackAcquired(nullptr);
OSScreenEnableEx(SCREEN_TV, 1); OSScreenEnableEx(SCREEN_TV, 1);
OSScreenEnableEx(SCREEN_DRC, 1); OSScreenEnableEx(SCREEN_DRC, 1);
ScreenUtils::OSScreenClear(CONSOLE_SCREEN_BOTH, WiiUScreen::consoleColor); ScreenUtils::OSScreenClear(CONSOLE_SCREEN_BOTH, WiiUScreen::consoleColor);
ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, WiiUScreen::ProcCallbackAcquired, nullptr, 100); ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, WiiUScreen::ProcCallbackAcquired, nullptr, 100);
ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, WiiUScreen::ProcCallbackReleased, nullptr, 100); ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, WiiUScreen::ProcCallbackReleased, nullptr, 100);
return true; return true;
} }
void WiiUScreen::DeInit() { void WiiUScreen::DeInit() {
if (sConsoleHasForeground) { if (sConsoleHasForeground) {
OSScreenShutdown(); OSScreenShutdown();
WiiUScreen::ProcCallbackReleased(nullptr); WiiUScreen::ProcCallbackReleased(nullptr);
} }
} }
void WiiUScreen::drawLinef(const char *fmt, ...) { void WiiUScreen::drawLinef(const char *fmt, ...) {
char *buf = (char *) MEMAllocFromDefaultHeapEx(PRINTF_BUFFER_LENGTH, 4); char *buf = (char *) MEMAllocFromDefaultHeapEx(PRINTF_BUFFER_LENGTH, 4);
va_list va; va_list va;
if (!buf) { if (!buf) {
return; return;
} }
va_start(va, fmt); va_start(va, fmt);
vsnprintf(buf, PRINTF_BUFFER_LENGTH, fmt, va); vsnprintf(buf, PRINTF_BUFFER_LENGTH, fmt, va);
WiiUScreen::drawLine(buf); WiiUScreen::drawLine(buf);
MEMFreeToDefaultHeap(buf); MEMFreeToDefaultHeap(buf);
va_end(va); va_end(va);
} }
void WiiUScreen::drawLine() { void WiiUScreen::drawLine() {
WiiUScreen::drawLine(""); WiiUScreen::drawLine("");
} }
void WiiUScreen::drawLine(const char *msg) { void WiiUScreen::drawLine(const char *msg) {
ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_BOTH, 0, consoleCursorY++, msg); ScreenUtils::printTextOnScreen(CONSOLE_SCREEN_BOTH, 0, consoleCursorY++, msg);
} }
void WiiUScreen::flipBuffers() { void WiiUScreen::flipBuffers() {
ScreenUtils::flipBuffers(CONSOLE_SCREEN_BOTH); ScreenUtils::flipBuffers(CONSOLE_SCREEN_BOTH);
} }
void WiiUScreen::clearScreen() { void WiiUScreen::clearScreen() {
ScreenUtils::OSScreenClear(CONSOLE_SCREEN_BOTH, WiiUScreen::consoleColor); ScreenUtils::OSScreenClear(CONSOLE_SCREEN_BOTH, WiiUScreen::consoleColor);
consoleCursorY = 0; consoleCursorY = 0;
} }

View File

@ -1,53 +1,53 @@
#pragma once #pragma once
#include <whb/log.h> #include <whb/log.h>
#include <whb/log_console.h> #include <whb/log_console.h>
#include <coreinit/memheap.h> #include <coreinit/memheap.h>
#include <coreinit/cache.h> #include <coreinit/cache.h>
#include <coreinit/memfrmheap.h> #include <coreinit/memfrmheap.h>
#include <coreinit/memory.h> #include <coreinit/memory.h>
#include <coreinit/screen.h> #include <coreinit/screen.h>
#include <proc_ui/procui.h> #include <proc_ui/procui.h>
#include <cstring> #include <cstring>
#include "utils/logger.h" #include "logger.h"
#define NUM_LINES (16) #define NUM_LINES (16)
#define LINE_LENGTH (128) #define LINE_LENGTH (128)
#define CONSOLE_FRAME_HEAP_TAG (0x000DECAF) #define CONSOLE_FRAME_HEAP_TAG (0x000DECAF)
#define PRINTF_BUFFER_LENGTH 2048 #define PRINTF_BUFFER_LENGTH 2048
#define DEBUG_CONSOLE_LOG(FMT, ARGS...)do { \ #define DEBUG_CONSOLE_LOG(FMT, ARGS...)do { \
DEBUG_FUNCTION_LINE(FMT, ## ARGS); \ DEBUG_FUNCTION_LINE(FMT, ## ARGS); \
WiiUScreen::drawLinef(FMT, ## ARGS); \ WiiUScreen::drawLinef(FMT, ## ARGS); \
} while (0) } while (0)
class WiiUScreen { class WiiUScreen {
public: public:
static uint32_t ProcCallbackAcquired(void *context); static uint32_t ProcCallbackAcquired(void *context);
static uint32_t ProcCallbackReleased(void *context); static uint32_t ProcCallbackReleased(void *context);
static bool Init(); static bool Init();
static void DeInit(); static void DeInit();
static void drawLinef(const char *fmt, ...); static void drawLinef(const char *fmt, ...);
static void drawLine(const char *fmt); static void drawLine(const char *fmt);
static void drawLine(); static void drawLine();
static void flipBuffers(); static void flipBuffers();
static void clearScreen(); static void clearScreen();
private: private:
static void *sBufferTV, *sBufferDRC; static void *sBufferTV, *sBufferDRC;
static uint32_t sBufferSizeTV, sBufferSizeDRC; static uint32_t sBufferSizeTV, sBufferSizeDRC;
static bool sConsoleHasForeground; static bool sConsoleHasForeground;
static uint32_t consoleColor; static uint32_t consoleColor;
static uint32_t consoleCursorY; static uint32_t consoleCursorY;
}; };