mirror of
https://github.com/wiiu-env/AutobootModule.git
synced 2024-11-25 12:06:58 +01:00
Menus support all controllers
This commit is contained in:
parent
10161be0a2
commit
4e821e4fa2
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
134
source/InputUtils.cpp
Normal 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
17
source/InputUtils.h
Normal 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();
|
||||||
|
};
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
Loading…
Reference in New Issue
Block a user