From 1ffb9cf65afe20257c39f3d5a36ca38fc108d381 Mon Sep 17 00:00:00 2001 From: Maschell Date: Thu, 30 Jan 2025 18:26:01 +0100 Subject: [PATCH 1/8] feat: Show notification is plugin is missing or module was never initialized --- Dockerfile | 2 +- plugin/src/main.cpp | 3 ++- plugin/src/module.cpp | 19 +++++++++++++++++-- plugin/src/module.h | 1 + src/config.cpp | 1 + src/config.h | 2 ++ src/main.cpp | 34 +++++++++++++++++++++------------- 7 files changed, 45 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index f746cda..24f8a62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ COPY --from=ghcr.io/wiiu-env/libnotifications:20240426 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20230621 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libkernel:20230621 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libmocha:20231127 /artifacts $DEVKITPRO -COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20240424 /artifacts $DEVKITPRO +COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:0.3.3-dev-20250130-474ef70 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:20240505 /artifacts $DEVKITPRO WORKDIR /app diff --git a/plugin/src/main.cpp b/plugin/src/main.cpp index 4845a38..73968ea 100644 --- a/plugin/src/main.cpp +++ b/plugin/src/main.cpp @@ -62,7 +62,8 @@ DEINITIALIZE_PLUGIN() { } ON_APPLICATION_START() { - + // Tell the module the plugin is running! + Inkay_SetPluginRunning(); } ON_APPLICATION_ENDS() { diff --git a/plugin/src/module.cpp b/plugin/src/module.cpp index 5fd9c2a..c20d980 100644 --- a/plugin/src/module.cpp +++ b/plugin/src/module.cpp @@ -15,17 +15,18 @@ */ #include "module.h" -#include -#include "config.h" #include "Notification.h" #include "utils/logger.h" #include "sysconfig.h" #include "lang.h" +#include + static OSDynLoad_Module module; static void (*moduleInitialize)(bool) = nullptr; static InkayStatus (*moduleGetStatus)() = nullptr; +static void (*moduleSetPluginRunning)() = nullptr; static const char *get_module_not_found_message() { return get_config_strings(get_system_language()).module_not_found.data(); @@ -61,6 +62,7 @@ void Inkay_Finalize() { OSDynLoad_Release(module); moduleInitialize = nullptr; moduleGetStatus = nullptr; + moduleSetPluginRunning = nullptr; } } @@ -76,3 +78,16 @@ InkayStatus Inkay_GetStatus() { return moduleGetStatus(); } + +void Inkay_SetPluginRunning() { + if (!module) { + return; + } + + if (!moduleSetPluginRunning && OSDynLoad_FindExport(module, OS_DYNLOAD_EXPORT_FUNC, "Inkay_SetPluginRunning", reinterpret_cast(&moduleSetPluginRunning)) != OS_DYNLOAD_OK) { + DEBUG_FUNCTION_LINE("Failed to find \"Inkay_SetPluginRunning\" function"); + return; + } + + moduleSetPluginRunning(); +} diff --git a/plugin/src/module.h b/plugin/src/module.h index b6247a4..ab7836d 100644 --- a/plugin/src/module.h +++ b/plugin/src/module.h @@ -27,3 +27,4 @@ enum class InkayStatus { void Inkay_Initialize(bool apply_patches); void Inkay_Finalize(); InkayStatus Inkay_GetStatus(); +void Inkay_SetPluginRunning(); diff --git a/src/config.cpp b/src/config.cpp index 56c8740..06e1a8f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -20,3 +20,4 @@ bool Config::connect_to_network = false; bool Config::initialized = false; bool Config::shown_uninitialized_warning = false; +bool Config::plugin_is_loaded = false; diff --git a/src/config.h b/src/config.h index 96f6775..0d4da6b 100644 --- a/src/config.h +++ b/src/config.h @@ -15,6 +15,8 @@ public: static bool initialized; static bool shown_uninitialized_warning; + + static bool plugin_is_loaded; }; #endif //INKAY_CONFIG_H diff --git a/src/main.cpp b/src/main.cpp index 7c4612d..fa9b9d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,6 +118,10 @@ static const char *get_pretendo_message() { return get_config_strings(get_system_language()).using_pretendo_network.data(); } +static void Inkay_SetPluginRunning() { + Config::plugin_is_loaded = true; +} + static InkayStatus Inkay_GetStatus() { if (!Config::initialized) return InkayStatus::Uninitialized; @@ -131,7 +135,7 @@ static InkayStatus Inkay_GetStatus() { static void Inkay_Initialize(bool apply_patches) { if (Config::initialized) - return; + return; // if using pretendo then (try to) apply the ssl patches if (apply_patches) { @@ -177,9 +181,7 @@ WUMS_INITIALIZE() { WHBLogCafeInit(); WHBLogUdpInit(); - auto res = Mocha_InitLibrary(); - - if (res != MOCHA_RESULT_SUCCESS) { + if (const auto res = Mocha_InitLibrary(); res != MOCHA_RESULT_SUCCESS) { DEBUG_FUNCTION_LINE("Mocha init failed with code %d!", res); return; } @@ -207,14 +209,8 @@ WUMS_DEINITIALIZE() { WUMS_APPLICATION_STARTS() { DEBUG_FUNCTION_LINE_VERBOSE("Inkay " INKAY_VERSION " starting up...\n"); - // TODO - Add a way to reliably check this. We can't do it here since this path gets triggered before - // the plugin gets initialized. - // - // if (!Config::initialized && !Config::shown_uninitialized_warning) { - // DEBUG_FUNCTION_LINE("Inkay module not initialized"); - // ShowNotification("Inkay module was not initialized. Ensure you have the Inkay plugin loaded"); - // Config::shown_uninitialized_warning = true; - // } + // Reset plugin loaded flag + Config::plugin_is_loaded = false; setup_olv_libs(); peertopeer_patch(); @@ -222,9 +218,21 @@ WUMS_APPLICATION_STARTS() { hotpatchAccountSettings(); } -WUMS_APPLICATION_ENDS() { +WUMS_ALL_APPLICATION_STARTS_DONE() { + if (Config::initialized && !Config::plugin_is_loaded) { + DEBUG_FUNCTION_LINE("Inkay is running but the plugin got unloaded"); + ShowNotification("Inkay module is still running. Please restart the console to disable Pretendo."); + Config::shown_uninitialized_warning = true; + } else if (!Config::initialized && !Config::shown_uninitialized_warning) { + DEBUG_FUNCTION_LINE("Inkay module not initialized"); + ShowNotification("Inkay module was not initialized. Ensure you have the Inkay plugin loaded"); + Config::shown_uninitialized_warning = true; + } +} +WUMS_APPLICATION_ENDS() { } WUMS_EXPORT_FUNCTION(Inkay_Initialize); WUMS_EXPORT_FUNCTION(Inkay_GetStatus); +WUMS_EXPORT_FUNCTION(Inkay_SetPluginRunning); From cc3fac1cc77ebbbe4606cf262f7d0dd7650f20de Mon Sep 17 00:00:00 2001 From: Maschell Date: Thu, 30 Jan 2025 18:27:20 +0100 Subject: [PATCH 2/8] (chore): clean up includes --- plugin/src/config.cpp | 1 + src/main.cpp | 35 ++++++++++++----------------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/plugin/src/config.cpp b/plugin/src/config.cpp index 0b99ffa..98c2323 100644 --- a/plugin/src/config.cpp +++ b/plugin/src/config.cpp @@ -33,6 +33,7 @@ #include #include #include + #include static config_strings strings; diff --git a/src/main.cpp b/src/main.cpp index fa9b9d4..502aab8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,22 +16,6 @@ along with this program. If not, see . */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "export.h" #include "iosu_url_patches.h" #include "config.h" @@ -39,16 +23,22 @@ #include "patches/olv_urls.h" #include "patches/game_matchmaking.h" -#include -#include +#include + +#include +#include + +#include +#include + #include -#include -#include +#include + +#include +#include #include "ca_pem.h" -#include - #define INKAY_VERSION "v2.6.0" /** @@ -67,7 +57,6 @@ WUMS_DEPENDS_ON(homebrew_notifications); WUMS_USE_WUT_DEVOPTAB(); -#include #include #include #include "patches/account_settings.h" From 24f680c6fbe0d47f9155622ff867200d0b44b148 Mon Sep 17 00:00:00 2001 From: Maschell Date: Mon, 3 Feb 2025 12:44:29 +0100 Subject: [PATCH 3/8] fix: Only do function patches if the plugin had to to update init Inkay --- src/config.cpp | 1 + src/config.h | 2 ++ src/main.cpp | 12 +++++++----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index 06e1a8f..5fdb3f0 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -17,6 +17,7 @@ #include "config.h" +bool Config::internal_init_done = false; bool Config::connect_to_network = false; bool Config::initialized = false; bool Config::shown_uninitialized_warning = false; diff --git a/src/config.h b/src/config.h index 0d4da6b..6e82ff7 100644 --- a/src/config.h +++ b/src/config.h @@ -10,6 +10,8 @@ class Config { public: + static bool internal_init_done; + static bool connect_to_network; static bool initialized; diff --git a/src/main.cpp b/src/main.cpp index 502aab8..0c189be 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -200,14 +200,16 @@ WUMS_APPLICATION_STARTS() { // Reset plugin loaded flag Config::plugin_is_loaded = false; - - setup_olv_libs(); - peertopeer_patch(); - matchmaking_notify_titleswitch(); - hotpatchAccountSettings(); } WUMS_ALL_APPLICATION_STARTS_DONE() { + if (!Config::internal_init_done) { + setup_olv_libs(); + peertopeer_patch(); + matchmaking_notify_titleswitch(); + hotpatchAccountSettings(); + Config::internal_init_done = true; + } if (Config::initialized && !Config::plugin_is_loaded) { DEBUG_FUNCTION_LINE("Inkay is running but the plugin got unloaded"); ShowNotification("Inkay module is still running. Please restart the console to disable Pretendo."); From e2cf529b3fcd7da7d78e8525777e6d9e15d70ff6 Mon Sep 17 00:00:00 2001 From: Maschell Date: Mon, 3 Feb 2025 12:45:17 +0100 Subject: [PATCH 4/8] fix: Only allow the plugin to init Inkay at boot to avoid potential crashes --- src/config.cpp | 1 + src/config.h | 2 ++ src/main.cpp | 12 +++++++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/config.cpp b/src/config.cpp index 5fdb3f0..9201ffd 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -22,3 +22,4 @@ bool Config::connect_to_network = false; bool Config::initialized = false; bool Config::shown_uninitialized_warning = false; bool Config::plugin_is_loaded = false; +bool Config::block_initialize = false; diff --git a/src/config.h b/src/config.h index 6e82ff7..64a2c6c 100644 --- a/src/config.h +++ b/src/config.h @@ -19,6 +19,8 @@ public: static bool shown_uninitialized_warning; static bool plugin_is_loaded; + + static bool block_initialize; }; #endif //INKAY_CONFIG_H diff --git a/src/main.cpp b/src/main.cpp index 0c189be..b06dde2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -126,6 +126,11 @@ static void Inkay_Initialize(bool apply_patches) { if (Config::initialized) return; + if (Config::block_initialize) { + ShowNotification("Failed to init Inkay. Please restart the console to use Pretendo"); + return; + } + // if using pretendo then (try to) apply the ssl patches if (apply_patches) { Config::connect_to_network = true; @@ -212,13 +217,18 @@ WUMS_ALL_APPLICATION_STARTS_DONE() { } if (Config::initialized && !Config::plugin_is_loaded) { DEBUG_FUNCTION_LINE("Inkay is running but the plugin got unloaded"); - ShowNotification("Inkay module is still running. Please restart the console to disable Pretendo."); + if (!Config::block_initialize) { + ShowNotification("Inkay module is still running. Please restart the console to disable Pretendo."); + } Config::shown_uninitialized_warning = true; } else if (!Config::initialized && !Config::shown_uninitialized_warning) { DEBUG_FUNCTION_LINE("Inkay module not initialized"); ShowNotification("Inkay module was not initialized. Ensure you have the Inkay plugin loaded"); Config::shown_uninitialized_warning = true; } + if (!Config::initialized) { + Config::block_initialize = true; + } } WUMS_APPLICATION_ENDS() { From 429d55ba9faaba9df32b65ee1dd7b21079296411 Mon Sep 17 00:00:00 2001 From: Maschell Date: Mon, 3 Feb 2025 19:38:44 +0100 Subject: [PATCH 5/8] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniel López Guimaraes <112760654+DaniElectra@users.noreply.github.com> --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b06dde2..8f8dcd4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -127,7 +127,7 @@ static void Inkay_Initialize(bool apply_patches) { return; if (Config::block_initialize) { - ShowNotification("Failed to init Inkay. Please restart the console to use Pretendo"); + ShowNotification("Cannot load Inkay while the system is running. Please restart the console"); return; } @@ -218,7 +218,7 @@ WUMS_ALL_APPLICATION_STARTS_DONE() { if (Config::initialized && !Config::plugin_is_loaded) { DEBUG_FUNCTION_LINE("Inkay is running but the plugin got unloaded"); if (!Config::block_initialize) { - ShowNotification("Inkay module is still running. Please restart the console to disable Pretendo."); + ShowNotification("Inkay module is still running. Please restart the console"); } Config::shown_uninitialized_warning = true; } else if (!Config::initialized && !Config::shown_uninitialized_warning) { From ed75702ac58a8e9389849894f2dd2d71a8a24282 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sat, 8 Feb 2025 23:04:53 +0100 Subject: [PATCH 6/8] Review fixes and update dockerfile --- Dockerfile | 2 +- src/config.cpp | 2 +- src/config.h | 2 +- src/main.cpp | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 24f8a62..46c49d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ COPY --from=ghcr.io/wiiu-env/libnotifications:20240426 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20230621 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libkernel:20230621 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libmocha:20231127 /artifacts $DEVKITPRO -COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:0.3.3-dev-20250130-474ef70 /artifacts $DEVKITPRO +COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20250208 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:20240505 /artifacts $DEVKITPRO WORKDIR /app diff --git a/src/config.cpp b/src/config.cpp index 9201ffd..d246580 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -20,6 +20,6 @@ bool Config::internal_init_done = false; bool Config::connect_to_network = false; bool Config::initialized = false; -bool Config::shown_uninitialized_warning = false; +bool Config::shown_warning = false; bool Config::plugin_is_loaded = false; bool Config::block_initialize = false; diff --git a/src/config.h b/src/config.h index 64a2c6c..966a655 100644 --- a/src/config.h +++ b/src/config.h @@ -16,7 +16,7 @@ public: static bool initialized; - static bool shown_uninitialized_warning; + static bool shown_warning; static bool plugin_is_loaded; diff --git a/src/main.cpp b/src/main.cpp index 8f8dcd4..9e3b085 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -220,11 +220,11 @@ WUMS_ALL_APPLICATION_STARTS_DONE() { if (!Config::block_initialize) { ShowNotification("Inkay module is still running. Please restart the console"); } - Config::shown_uninitialized_warning = true; - } else if (!Config::initialized && !Config::shown_uninitialized_warning) { + Config::shown_warning = true; + } else if (!Config::initialized && !Config::shown_warning) { DEBUG_FUNCTION_LINE("Inkay module not initialized"); ShowNotification("Inkay module was not initialized. Ensure you have the Inkay plugin loaded"); - Config::shown_uninitialized_warning = true; + Config::shown_warning = true; } if (!Config::initialized) { Config::block_initialize = true; From 79ccad1fd40a91b22895dceb6c718aa79cc009f2 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 9 Feb 2025 10:26:09 +0100 Subject: [PATCH 7/8] fix: Do title specific patches more than once --- src/config.cpp | 1 - src/config.h | 4 ---- src/main.cpp | 13 ++++++------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index d246580..66a78c4 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -17,7 +17,6 @@ #include "config.h" -bool Config::internal_init_done = false; bool Config::connect_to_network = false; bool Config::initialized = false; bool Config::shown_warning = false; diff --git a/src/config.h b/src/config.h index 966a655..8455bb0 100644 --- a/src/config.h +++ b/src/config.h @@ -5,12 +5,8 @@ #ifndef INKAY_CONFIG_H #define INKAY_CONFIG_H -#include -#include - class Config { public: - static bool internal_init_done; static bool connect_to_network; diff --git a/src/main.cpp b/src/main.cpp index 9e3b085..7e6d196 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -208,13 +208,12 @@ WUMS_APPLICATION_STARTS() { } WUMS_ALL_APPLICATION_STARTS_DONE() { - if (!Config::internal_init_done) { - setup_olv_libs(); - peertopeer_patch(); - matchmaking_notify_titleswitch(); - hotpatchAccountSettings(); - Config::internal_init_done = true; - } + // we need to do the patches here because otherwise the Config::connect_to_network flag might be set yet + setup_olv_libs(); + peertopeer_patch(); + matchmaking_notify_titleswitch(); + hotpatchAccountSettings(); + if (Config::initialized && !Config::plugin_is_loaded) { DEBUG_FUNCTION_LINE("Inkay is running but the plugin got unloaded"); if (!Config::block_initialize) { From 4a880c1a2e52ad591416e6289e9e84d4db541ad4 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 9 Feb 2025 10:26:48 +0100 Subject: [PATCH 8/8] feat: Check title version before doing game specific patches --- src/patches/account_settings.cpp | 10 ++++----- src/patches/game_peertopeer.cpp | 35 ++++++++++++++++++++++++++------ src/utils/rpl_info.cpp | 25 +++++++++++++++++++++++ src/utils/rpl_info.h | 2 ++ 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/patches/account_settings.cpp b/src/patches/account_settings.cpp index 3a0e7bb..cac45ba 100644 --- a/src/patches/account_settings.cpp +++ b/src/patches/account_settings.cpp @@ -24,12 +24,12 @@ #include "inkay_config.h" #include -#include -#include -#include + #include #include -#include + +#include +#include #include "ca_pem.h" // generated at buildtime @@ -163,7 +163,7 @@ bool hotpatchAccountSettings() { } void unpatchAccountSettings() { - for (auto handle: account_patches) { + for (const auto handle: account_patches) { FunctionPatcher_RemoveFunctionPatch(handle); } account_patches.clear(); diff --git a/src/patches/game_peertopeer.cpp b/src/patches/game_peertopeer.cpp index 2651156..d986f36 100644 --- a/src/patches/game_peertopeer.cpp +++ b/src/patches/game_peertopeer.cpp @@ -28,18 +28,23 @@ using namespace std::string_view_literals; static struct { std::array tid; + uint16_t version; uint32_t min_port_addr; uint32_t max_port_addr; std::string_view rpx; -} generic_patch_games [] = { - { // MARIO KART 8 - { 0x00050000'1010ec00, 0x00050000'1010ed00, 0x00050000'1010eb00 }, +} generic_patch_games[] = { + { + // MARIO KART 8 + {0x00050000'1010ec00, 0x00050000'1010ed00, 0x00050000'1010eb00}, + 81, 0x101a9a52, 0x101a9a54, "Turbo.rpx"sv, }, - { // Splatoon - { 0x00050000'10176900, 0x00050000'10176a00, 0x00050000'10162b00 }, + { + // Splatoon + {0x00050000'10176900, 0x00050000'10176a00, 0x00050000'10162b00}, + 288, 0x101e8952, 0x101e8954, "Gambit.rpx"sv, @@ -48,8 +53,16 @@ static struct { static void generic_peertopeer_patch() { uint64_t tid = OSGetTitleID(); + uint16_t title_version = 0; + if (const auto version_opt = get_current_title_version(); !version_opt) { + DEBUG_FUNCTION_LINE("Failed to detect current title version"); + return; + } else { + title_version = *version_opt; + DEBUG_FUNCTION_LINE("Title version detected: %d", title_version); + } - for (const auto& patch : generic_patch_games) { + for (const auto &patch: generic_patch_games) { if (std::ranges::find(patch.tid, tid) == patch.tid.end()) continue; std::optional game = search_for_rpl(patch.rpx); @@ -58,6 +71,12 @@ static void generic_peertopeer_patch() { return; } + if (title_version != patch.version) { + DEBUG_FUNCTION_LINE("Unexpected title version. Expected %d but got %d (%s)", patch.version, title_version, + patch.rpx.data()); + continue; + } + auto port = get_console_peertopeer_port(); DEBUG_FUNCTION_LINE_VERBOSE("Will use port %d. %08x", port, game->textAddr); @@ -76,6 +95,10 @@ static void minecraft_peertopeer_patch() { DEBUG_FUNCTION_LINE("Couldn't find minecraft rpx!"); return; } + if (const auto version_opt = get_current_title_version(); !version_opt || *version_opt != 688) { + DEBUG_FUNCTION_LINE("Wrong mincecraft version detected"); + return; + } auto port = get_console_peertopeer_port(); DEBUG_FUNCTION_LINE_VERBOSE("Will use port %d. %08x", port, minecraft->textAddr); diff --git a/src/utils/rpl_info.cpp b/src/utils/rpl_info.cpp index 2148e1e..1bfe9fb 100644 --- a/src/utils/rpl_info.cpp +++ b/src/utils/rpl_info.cpp @@ -16,6 +16,10 @@ #include #include #include +#include +#include + +#include "logger.h" // if we get more than like.. two callsites for this, it should really be refactored out rather than doing a fresh // search every time @@ -37,3 +41,24 @@ std::optional search_for_rpl(std::string_view name) { return *rpl; } + +std::optional get_current_title_version() { + const auto mcpHandle = MCP_Open(); + MCPTitleListType titleInfo; + int32_t res = -1; + const uint64_t curTitleId = OSGetTitleID(); + if ((curTitleId & 0x0000000F00000000) == 0) { + res = MCP_GetTitleInfo(mcpHandle, curTitleId | 0x0000000E00000000, &titleInfo); + } + if (res != 0) { + res = MCP_GetTitleInfo(mcpHandle, curTitleId, &titleInfo); + } + MCP_Close(mcpHandle); + if (res != 0) { + DEBUG_FUNCTION_LINE("Failed to get title version of %016llX.", curTitleId); + return {}; + } + MCP_Close(mcpHandle); + const auto tmp_result = titleInfo.titleVersion; // make the compiler happy because we access a packed struct + return tmp_result; +} diff --git a/src/utils/rpl_info.h b/src/utils/rpl_info.h index 15f59c7..c290fe8 100644 --- a/src/utils/rpl_info.h +++ b/src/utils/rpl_info.h @@ -26,3 +26,5 @@ constexpr void *rpl_addr(OSDynLoad_NotifyData rpl, uint32_t cemu_addr) { return (void *)(rpl.dataAddr + cemu_addr - 0x1000'0000); } } + +std::optional get_current_title_version(); \ No newline at end of file