mirror of
https://github.com/wiiu-env/AutobootModule.git
synced 2024-11-29 05:54:16 +01:00
Add support for custom boot entries (either vWii or Wiiu)
(cherry picked from commit 74316bd54d4d873d9bb453eb12747f84be5ae0d8)
This commit is contained in:
parent
2d023be0a2
commit
1711a30cf7
@ -12,6 +12,7 @@
|
|||||||
#include <nn/act.h>
|
#include <nn/act.h>
|
||||||
#include <nn/cmpt/cmpt.h>
|
#include <nn/cmpt/cmpt.h>
|
||||||
#include <padscore/kpad.h>
|
#include <padscore/kpad.h>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sysapp/launch.h>
|
#include <sysapp/launch.h>
|
||||||
#include <sysapp/title.h>
|
#include <sysapp/title.h>
|
||||||
@ -39,6 +40,18 @@ void bootHomebrewLauncher() {
|
|||||||
_SYSLaunchTitleWithStdArgsInNoSplash(titleId, nullptr);
|
_SYSLaunchTitleWithStdArgsInNoSplash(titleId, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bootWiiuTitle(const std::string &hexId) {
|
||||||
|
uint64_t titleId;
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::hex << hexId;
|
||||||
|
ss >> titleId;
|
||||||
|
|
||||||
|
handleAccountSelection();
|
||||||
|
|
||||||
|
titleId = _SYSGetSystemApplicationTitleId(static_cast<SYSTEM_APP_ID>(titleId));
|
||||||
|
_SYSLaunchTitleWithStdArgsInNoSplash(titleId, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void handleAccountSelection() {
|
void handleAccountSelection() {
|
||||||
nn::act::Initialize();
|
nn::act::Initialize();
|
||||||
nn::act::SlotNo defaultSlot = nn::act::GetDefaultAccount();
|
nn::act::SlotNo defaultSlot = nn::act::GetDefaultAccount();
|
||||||
@ -83,7 +96,7 @@ void handleAccountSelection() {
|
|||||||
nn::act::Finalize();
|
nn::act::Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void launchvWiiTitle(uint64_t titleId) {
|
void launchvWiiTitle(uint64_t titleId) {
|
||||||
// we need to init kpad for cmpt
|
// we need to init kpad for cmpt
|
||||||
KPADInit();
|
KPADInit();
|
||||||
|
|
||||||
@ -114,7 +127,7 @@ void bootvWiiMenu() {
|
|||||||
launchvWiiTitle(0);
|
launchvWiiTitle(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getVWiiHBLTitleId() {
|
uint64_t getVWiiTitleId(const std::string& hexId) {
|
||||||
// fall back to booting the vWii system menu if anything fails
|
// fall back to booting the vWii system menu if anything fails
|
||||||
uint64_t titleId = 0;
|
uint64_t titleId = 0;
|
||||||
|
|
||||||
@ -126,13 +139,15 @@ uint64_t getVWiiHBLTitleId() {
|
|||||||
if (FSAMount(client, "/dev/slccmpt01", "/vol/storage_slccmpt01", FSA_MOUNT_FLAG_GLOBAL_MOUNT, nullptr, 0) >= 0) {
|
if (FSAMount(client, "/dev/slccmpt01", "/vol/storage_slccmpt01", FSA_MOUNT_FLAG_GLOBAL_MOUNT, nullptr, 0) >= 0) {
|
||||||
FSStat stat;
|
FSStat stat;
|
||||||
|
|
||||||
// test if the OHBC or HBC is installed
|
const std::string hexValue{ hexId.size() > 2 ? hexId.substr(2) : hexId };
|
||||||
if (FSAGetStat(client, "/vol/storage_slccmpt01/title/00010001/4f484243/content/00000000.app", &stat) >= 0) {
|
const std::string titleString{ "/vol/storage_slccmpt01/title/00010001/" + hexValue + "/content/00000000.app" };
|
||||||
titleId = 0x000100014F484243L; // 'OHBC'
|
if (FSAGetStat(client, titleString.c_str(), &stat) >= 0) {
|
||||||
} else if (FSAGetStat(client, "/vol/storage_slccmpt01/title/00010001/4c554c5a/content/00000000.app", &stat) >= 0) {
|
std::stringstream ss;
|
||||||
titleId = 0x000100014C554C5AL; // 'LULZ'
|
ss << std::hex << hexId;
|
||||||
|
ss >> titleId;
|
||||||
|
titleId |= 0x0001000100000000L;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("Cannot find HBC");
|
DEBUG_FUNCTION_LINE("Cannot find title 0x%s", hexId.c_str());
|
||||||
}
|
}
|
||||||
FSAUnmount(client, "/vol/storage_slccmpt01", static_cast<FSAUnmountFlags>(2));
|
FSAUnmount(client, "/vol/storage_slccmpt01", static_cast<FSAUnmountFlags>(2));
|
||||||
} else {
|
} else {
|
||||||
@ -145,6 +160,17 @@ uint64_t getVWiiHBLTitleId() {
|
|||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to add FSAClient");
|
DEBUG_FUNCTION_LINE_ERR("Failed to add FSAClient");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return titleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getVWiiHBLTitleId() {
|
||||||
|
// Try 'OHBC' first and if it fails, try 'LULZ'
|
||||||
|
uint64_t titleId = getVWiiTitleId("4f484243");
|
||||||
|
if (titleId == 0) {
|
||||||
|
titleId = getVWiiTitleId("4c554c5a");
|
||||||
|
}
|
||||||
|
|
||||||
return titleId;
|
return titleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
void launchvWiiTitle(uint64_t titleId);
|
||||||
|
|
||||||
void bootWiiUMenu();
|
void bootWiiUMenu();
|
||||||
|
|
||||||
void bootHomebrewLauncher();
|
void bootHomebrewLauncher();
|
||||||
|
|
||||||
|
void bootWiiuTitle(const std::string& hexId);
|
||||||
|
|
||||||
void bootvWiiMenu();
|
void bootvWiiMenu();
|
||||||
|
|
||||||
void bootHomebrewChannel();
|
void bootHomebrewChannel();
|
||||||
|
|
||||||
|
uint64_t getVWiiTitleId(const std::string& hexId);
|
||||||
|
|
||||||
uint64_t getVWiiHBLTitleId();
|
uint64_t getVWiiHBLTitleId();
|
@ -11,18 +11,17 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <nn/act/client_cpp.h>
|
#include <nn/act/client_cpp.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <vpad/input.h>
|
#include <vpad/input.h>
|
||||||
|
|
||||||
#define AUTOBOOT_MODULE_VERSION "v0.1.2"
|
#define AUTOBOOT_MODULE_VERSION "v0.1.2"
|
||||||
|
|
||||||
const char *autoboot_config_strings[] = {
|
// Initialize with the autoboot_base_config_strings data
|
||||||
"wiiu_menu",
|
std::vector<std::string> autoboot_config_strings = { autoboot_base_config_strings.begin(), autoboot_base_config_strings.end() };
|
||||||
"homebrew_launcher",
|
std::vector<BootOption> custom_boot_options;
|
||||||
"vwii_system_menu",
|
|
||||||
"vwii_homebrew_channel",
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
std::string string_format(const std::string &format, Args... args) {
|
std::string string_format(const std::string &format, Args... args) {
|
||||||
@ -33,36 +32,90 @@ std::string string_format(const std::string &format, Args... args) {
|
|||||||
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t readAutobootOption(std::string &configPath) {
|
std::string trim(const std::string& str) {
|
||||||
FILE *f = fopen(configPath.c_str(), "r");
|
std::string result;
|
||||||
if (f) {
|
for (auto& ch : str) {
|
||||||
char buf[128]{};
|
if (!std::isspace(ch)) {
|
||||||
fgets(buf, sizeof(buf), f);
|
result += ch;
|
||||||
fclose(f);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < sizeof(autoboot_config_strings) / sizeof(char *); i++) {
|
return result;
|
||||||
if (strncmp(autoboot_config_strings[i], buf, strlen(autoboot_config_strings[i])) == 0) {
|
}
|
||||||
|
|
||||||
|
void readBootOptionsFromSD(const std::string &configPath) {
|
||||||
|
std::ifstream fileStream(configPath.c_str(), std::ios::in);
|
||||||
|
if (fileStream.is_open()) {
|
||||||
|
DEBUG_FUNCTION_LINE("bootOptions.cfg open");
|
||||||
|
|
||||||
|
constexpr size_t bufSize{ 256 };
|
||||||
|
for (char line[bufSize]; fileStream.getline(line, bufSize);) {
|
||||||
|
DEBUG_FUNCTION_LINE(" Line \"%s\"", line);
|
||||||
|
std::istringstream parsingLine{std::string{line}};
|
||||||
|
memset(line, 0, bufSize);
|
||||||
|
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
for (char tmp[bufSize]; parsingLine.getline(tmp, bufSize, ',');) {
|
||||||
|
DEBUG_FUNCTION_LINE(" Token \"%s\"", tmp);
|
||||||
|
tokens.push_back(trim(tmp));
|
||||||
|
memset(tmp, 0, bufSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokens.size() == 3)
|
||||||
|
{
|
||||||
|
const std::string subSystem{ tokens[2] };
|
||||||
|
const std::string vWiiStr{ "vwii" };
|
||||||
|
const bool vWii{ std::equal(subSystem.begin(), subSystem.end(),
|
||||||
|
vWiiStr.begin(), vWiiStr.end(), [](unsigned char a, unsigned char b) {
|
||||||
|
return std::tolower(a) == std::tolower(b);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
custom_boot_options.push_back(BootOption{tokens[0], tokens[1], vWii});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE("Failed to open bootOptions.cfg");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t readAutobootOption(const std::string &configPath) {
|
||||||
|
std::ifstream fileStream(configPath.c_str(), std::ios::in);
|
||||||
|
if (fileStream.is_open()) {
|
||||||
|
std::string readOption;
|
||||||
|
fileStream >> readOption;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < autoboot_config_strings.size(); ++i) {
|
||||||
|
if (autoboot_config_strings[i] == readOption) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < custom_boot_options.size(); ++i) {
|
||||||
|
if (custom_boot_options[i].title == readOption) {
|
||||||
|
return BOOT_OPTION_MAX_OPTIONS + i;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeAutobootOption(std::string &configPath, int32_t autobootOption) {
|
void writeAutobootOption(const std::string &configPath, int32_t autobootOption) {
|
||||||
FILE *f = fopen(configPath.c_str(), "w");
|
const int32_t customAutoBootOption{ autobootOption - BOOT_OPTION_MAX_OPTIONS };
|
||||||
if (f) {
|
std::ofstream outStream(configPath.c_str(), std::ios::out);
|
||||||
if (autobootOption >= 0) {
|
if (outStream.is_open()) {
|
||||||
fputs(autoboot_config_strings[autobootOption], f);
|
if (customAutoBootOption >= 0) {
|
||||||
|
outStream << custom_boot_options[customAutoBootOption].title;
|
||||||
|
} else if (autobootOption >= 0) {
|
||||||
|
outStream << autoboot_config_strings[autobootOption];
|
||||||
} else {
|
} else {
|
||||||
fputs("none", f);
|
outStream << "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, const std::map<uint32_t, std::string> &menu) {
|
int32_t handleMenuScreen(const 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) {
|
||||||
OSFatal("Failed to alloc memory for screen");
|
OSFatal("Failed to alloc memory for screen");
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ACTAccountInfo.h"
|
#include "ACTAccountInfo.h"
|
||||||
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -20,18 +21,38 @@
|
|||||||
#define COLOR_BORDER Color(204, 204, 204, 255)
|
#define COLOR_BORDER Color(204, 204, 204, 255)
|
||||||
#define COLOR_BORDER_HIGHLIGHTED Color(0x3478e4ff)
|
#define COLOR_BORDER_HIGHLIGHTED Color(0x3478e4ff)
|
||||||
|
|
||||||
|
struct BootOption {
|
||||||
|
std::string title;
|
||||||
|
std::string hexId;
|
||||||
|
bool vWii;
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BOOT_OPTION_WII_U_MENU,
|
BOOT_OPTION_WII_U_MENU = 0,
|
||||||
BOOT_OPTION_HOMEBREW_LAUNCHER,
|
BOOT_OPTION_HOMEBREW_LAUNCHER,
|
||||||
BOOT_OPTION_VWII_SYSTEM_MENU,
|
BOOT_OPTION_VWII_SYSTEM_MENU,
|
||||||
BOOT_OPTION_VWII_HOMEBREW_CHANNEL,
|
BOOT_OPTION_VWII_HOMEBREW_CHANNEL,
|
||||||
|
|
||||||
|
BOOT_OPTION_MAX_OPTIONS
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t readAutobootOption(std::string &configPath);
|
constexpr std::array<const char*, BOOT_OPTION_MAX_OPTIONS> autoboot_base_config_strings{
|
||||||
|
"wiiu_menu",
|
||||||
|
"homebrew_launcher",
|
||||||
|
"vwii_system_menu",
|
||||||
|
"vwii_homebrew_channel",
|
||||||
|
};
|
||||||
|
|
||||||
void writeAutobootOption(std::string &configPath, int32_t autobootOption);
|
extern std::vector<std::string> autoboot_config_strings;
|
||||||
|
extern std::vector<BootOption> custom_boot_options;
|
||||||
|
|
||||||
int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, const std::map<uint32_t, std::string> &menu);
|
void readBootOptionsFromSD(const std::string &configPath);
|
||||||
|
|
||||||
|
int32_t readAutobootOption(const std::string &configPath);
|
||||||
|
|
||||||
|
void writeAutobootOption(const std::string &configPath, int32_t autobootOption);
|
||||||
|
|
||||||
|
int32_t handleMenuScreen(const std::string &configPath, int32_t autobootOptionInput, const std::map<uint32_t, std::string> &menu);
|
||||||
|
|
||||||
nn::act::SlotNo handleAccountSelectScreen(const std::vector<std::shared_ptr<AccountInfo>> &data);
|
nn::act::SlotNo handleAccountSelectScreen(const std::vector<std::shared_ptr<AccountInfo>> &data);
|
||||||
|
|
||||||
|
@ -81,6 +81,10 @@ int32_t main(int32_t argc, char **argv) {
|
|||||||
if (stat(hblInstallerPath.c_str(), &st) >= 0) {
|
if (stat(hblInstallerPath.c_str(), &st) >= 0) {
|
||||||
showHBL = true;
|
showHBL = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readBootOptionsFromSD(std::string(argv[0]) + "/bootOptions.cfg");
|
||||||
|
} else {
|
||||||
|
readBootOptionsFromSD("fs:/vol/external01/wiiu/bootOptions.cfg");
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t bootSelection = readAutobootOption(configPath);
|
int32_t bootSelection = readAutobootOption(configPath);
|
||||||
@ -95,6 +99,11 @@ int32_t main(int32_t argc, char **argv) {
|
|||||||
menu[BOOT_OPTION_VWII_HOMEBREW_CHANNEL] = "vWii Homebrew Channel";
|
menu[BOOT_OPTION_VWII_HOMEBREW_CHANNEL] = "vWii Homebrew Channel";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < custom_boot_options.size(); ++i) {
|
||||||
|
const BootOption& option{ custom_boot_options[i] };
|
||||||
|
menu[BOOT_OPTION_MAX_OPTIONS + i] = option.title + " (" + (option.vWii ? "vWii" : "WiiU") + " " + option.hexId + ")";
|
||||||
|
}
|
||||||
|
|
||||||
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) ||
|
||||||
@ -102,7 +111,22 @@ int32_t main(int32_t argc, char **argv) {
|
|||||||
bootSelection = handleMenuScreen(configPath, bootSelection, menu);
|
bootSelection = handleMenuScreen(configPath, bootSelection, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bootSelection >= 0) {
|
const int32_t customBootSelection{bootSelection - BOOT_OPTION_MAX_OPTIONS};
|
||||||
|
if (customBootSelection >= 0) {
|
||||||
|
if (static_cast<size_t>(customBootSelection) < custom_boot_options.size()) {
|
||||||
|
const BootOption &selectedOption{custom_boot_options[customBootSelection]};
|
||||||
|
if (selectedOption.vWii) {
|
||||||
|
const uint64_t titleId = getVWiiTitleId(selectedOption.hexId);
|
||||||
|
DEBUG_FUNCTION_LINE("Launching vWii title %016llx", titleId);
|
||||||
|
launchvWiiTitle(titleId);
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE("Launching WiiU title %s", selectedOption.hexId);
|
||||||
|
bootWiiuTitle(selectedOption.hexId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bootWiiUMenu();
|
||||||
|
}
|
||||||
|
} else if (bootSelection >= 0) {
|
||||||
switch (bootSelection) {
|
switch (bootSelection) {
|
||||||
case BOOT_OPTION_WII_U_MENU:
|
case BOOT_OPTION_WII_U_MENU:
|
||||||
bootWiiUMenu();
|
bootWiiUMenu();
|
||||||
|
Loading…
Reference in New Issue
Block a user