From 9a8ee29c6bd372b086145450b26f36849a1c2905 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 2 Apr 2023 11:59:16 +0200 Subject: [PATCH] Improve disc launching in quick start menu --- Dockerfile | 2 +- source/MenuUtils.cpp | 112 +++++++++++++++++++++++++++++++++++++ source/MenuUtils.h | 2 + source/QuickStartUtils.cpp | 28 +++++++--- source/utils.cpp | 33 +++++++++++ source/utils.h | 2 + 6 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 source/utils.cpp diff --git a/Dockerfile b/Dockerfile index b85f491..5e779d3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ghcr.io/wiiu-env/devkitppc:20221228 +FROM ghcr.io/wiiu-env/devkitppc:20230402 COPY --from=ghcr.io/wiiu-env/libmocha:20220919 /artifacts $DEVKITPRO diff --git a/source/MenuUtils.cpp b/source/MenuUtils.cpp index 06cf9c7..285b7a1 100644 --- a/source/MenuUtils.cpp +++ b/source/MenuUtils.cpp @@ -3,15 +3,19 @@ #include "DrawUtils.h" #include "icon_png.h" #include "logger.h" +#include "utils.h" #include "version.h" #include +#include #include +#include #include #include #include #include #include #include +#include #include #include @@ -414,3 +418,111 @@ void handleUpdateWarningScreen() { free(screenBuffer); } + +bool handleDiscInsertScreen(uint64_t expectedTitleId, uint64_t *titleIdToLaunch) { + if (titleIdToLaunch == nullptr) { + DEBUG_FUNCTION_LINE_ERR("titleIdToLaunch is NULL"); + return false; + } + + if (SYSCheckTitleExists(expectedTitleId)) { + *titleIdToLaunch = expectedTitleId; + return true; + } + + auto result = false; + auto screenBuffer = DrawUtils::InitOSScreen(); + if (!screenBuffer) { + OSFatal("Failed to alloc memory for screen"); + } + + uint32_t tvBufferSize = OSScreenGetBufferSizeEx(SCREEN_TV); + uint32_t drcBufferSize = OSScreenGetBufferSizeEx(SCREEN_DRC); + + DrawUtils::initBuffers(screenBuffer, tvBufferSize, (void *) ((uint32_t) screenBuffer + tvBufferSize), drcBufferSize); + if (!DrawUtils::initFont()) { + OSFatal("Failed to init font"); + } + DrawUtils::beginDraw(); + DrawUtils::clear(COLOR_BACKGROUND); + DrawUtils::endDraw(); + + uint64_t titleIdOfDisc = 0; + bool discInserted; + + uint32_t attempt = 0; + while (!GetTitleIdOfDisc(&titleIdOfDisc, &discInserted)) { + if (++attempt > 20) { + break; + } + OSSleepTicks(OSMillisecondsToTicks(100)); + } + + bool wrongDiscInserted = discInserted && (titleIdOfDisc != expectedTitleId); + + if (discInserted && !wrongDiscInserted) { + *titleIdToLaunch = expectedTitleId; + DrawUtils::deinitFont(); + free(screenBuffer); + 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. + bool allowDisc = !wrongDiscInserted; + while (true) { + VPADStatus vpad{}; + VPADRead(VPAD_CHAN_0, &vpad, 1, nullptr); + + if (vpad.trigger & VPAD_BUTTON_A) { + result = false; + break; + } + + 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::clear(COLOR_BLACK); + DrawUtils::endDraw(); + + DrawUtils::deinitFont(); + + free(screenBuffer); + + return result; +} diff --git a/source/MenuUtils.h b/source/MenuUtils.h index 1129674..8f5fcd5 100644 --- a/source/MenuUtils.h +++ b/source/MenuUtils.h @@ -36,3 +36,5 @@ int32_t handleMenuScreen(std::string &configPath, int32_t autobootOptionInput, c nn::act::SlotNo handleAccountSelectScreen(const std::vector> &data); void handleUpdateWarningScreen(); + +bool handleDiscInsertScreen(uint64_t expectedTitleId, uint64_t *titleIdToLaunch); diff --git a/source/QuickStartUtils.cpp b/source/QuickStartUtils.cpp index ddbd7d8..77f5b4b 100644 --- a/source/QuickStartUtils.cpp +++ b/source/QuickStartUtils.cpp @@ -1,6 +1,7 @@ #include #include "BootUtils.h" +#include "MenuUtils.h" #include "QuickStartUtils.h" #include "logger.h" @@ -124,8 +125,6 @@ bool getQuickBoot() { return false; } - DEBUG_FUNCTION_LINE("Trying to autoboot for titleId %016llX", info.titleId); - if (info.titleId == 0x0005001010040000L || info.titleId == 0x0005001010040100L || info.titleId == 0x0005001010040200L) { @@ -207,21 +206,36 @@ bool getQuickBoot() { return true; } - if (!SYSCheckTitleExists(info.titleId)) { - DEBUG_FUNCTION_LINE("Title %016llX doesn't exist", info.titleId); - return false; + uint64_t titleIdToLaunch = info.titleId; + + switch (info.mediaType) { + case nn::sl::NN_SL_MEDIA_TYPE_ODD: { + if (!handleDiscInsertScreen(titleIdToLaunch, &titleIdToLaunch)) { + DEBUG_FUNCTION_LINE("Launch Wii U Menu!"); + return false; + } + break; + } + default: { + if (!SYSCheckTitleExists(titleIdToLaunch)) { + DEBUG_FUNCTION_LINE("Title %016llX doesn't exist", titleIdToLaunch); + return false; + } + } } MCPTitleListType titleInfo; int32_t handle = MCP_Open(); - auto err = MCP_GetTitleInfo(handle, info.titleId, &titleInfo); + auto err = MCP_GetTitleInfo(handle, titleIdToLaunch, &titleInfo); MCP_Close(handle); if (err == 0) { + DEBUG_FUNCTION_LINE("Launch %016llX", titleIdToLaunch); ACPAssignTitlePatch(&titleInfo); - _SYSLaunchTitleWithStdArgsInNoSplash(info.titleId, nullptr); + _SYSLaunchTitleWithStdArgsInNoSplash(titleIdToLaunch, nullptr); return true; } + DEBUG_FUNCTION_LINE("Launch Wii U Menu!"); return false; } else { DEBUG_FUNCTION_LINE("No quick start"); diff --git a/source/utils.cpp b/source/utils.cpp new file mode 100644 index 0000000..ef37365 --- /dev/null +++ b/source/utils.cpp @@ -0,0 +1,33 @@ +#include "logger.h" +#include + +bool GetTitleIdOfDisc(uint64_t *titleId, bool *discPresent) { + if (discPresent) { + *discPresent = false; + } + alignas(0x40) MCPTitleListType titles[4]; + uint32_t count = 0; + + int handle = MCP_Open(); + if (handle < 0) { + DEBUG_FUNCTION_LINE_ERR("MCP_Open failed"); + return false; + } + auto res = MCP_TitleListByDeviceType(handle, MCP_DEVICE_TYPE_ODD, &count, titles, sizeof(titles)); + MCP_Close(handle); + + if (res >= 0 && count > 0) { + if (discPresent) { + *discPresent = true; + } + for (uint32_t i = 0; i < count; i++) { + if ((titles[i].titleId & 0xFFFFFFFF00000000L) == (0x0005000000000000)) { + if (titleId) { + *titleId = titles[i].titleId; + } + return true; + } + } + } + return false; +} \ No newline at end of file diff --git a/source/utils.h b/source/utils.h index 1ccac85..ba78faf 100644 --- a/source/utils.h +++ b/source/utils.h @@ -18,3 +18,5 @@ template std::shared_ptr make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std::forward(args)...))) { return std::shared_ptr(new (std::nothrow) T(std::forward(args)...)); } + +bool GetTitleIdOfDisc(uint64_t *titleId, bool *discPresent); \ No newline at end of file