diff --git a/source/PluginManagement.cpp b/source/PluginManagement.cpp index 3999ef1..7278879 100644 --- a/source/PluginManagement.cpp +++ b/source/PluginManagement.cpp @@ -3,6 +3,7 @@ #include "hooks.h" #include "plugin/PluginContainer.h" #include "plugin/PluginLinkInformationFactory.h" +#include "plugin/PluginLoadWrapper.h" #include "plugin/PluginMetaInformationFactory.h" #include "utils/ElfUtils.h" #include "utils/StringTools.h" @@ -10,47 +11,32 @@ #include #include #include -#include - -bool CheckIfAllowed(const PluginMetaInformation &metaInfo) { - std::vector> allowList = { - {"Maschell", "Aroma Base Plugin"}, - {"Maschell", "DRC Region Free Plugin"}, - {"Maschell", "Homebrew on Wii U menu"}, - {"Maschell", "Region Free Plugin"}, - {"Maschell", "Wiiload"}, - {"mtheall, Maschell", "ftpiiu"}, - }; - return std::any_of(allowList.begin(), allowList.end(), [&metaInfo](const auto &cur) { - return metaInfo.getAuthor() == cur.first && metaInfo.getName() == cur.second; - }); -} std::vector -PluginManagement::loadPlugins(const std::set> &pluginDataList, std::vector &trampolineData) { +PluginManagement::loadPlugins(const std::vector &pluginDataList, std::vector &trampolineData) { std::vector plugins; uint32_t trampolineID = 0; - for (const auto &pluginData : pluginDataList) { + for (const auto &pluginDataWrapper : pluginDataList) { PluginParseErrors error = PLUGIN_PARSE_ERROR_UNKNOWN; - auto metaInfo = PluginMetaInformationFactory::loadPlugin(*pluginData, error); + auto metaInfo = PluginMetaInformationFactory::loadPlugin(*pluginDataWrapper.getPluginData(), error); if (metaInfo && error == PLUGIN_PARSE_ERROR_NONE) { - if (!pluginData->getSource().ends_with(".wps") || CheckIfAllowed(*metaInfo)) { + if (pluginDataWrapper.isLoadAndLink()) { DEBUG_FUNCTION_LINE_INFO("We want to link %s by %s", metaInfo->getName().c_str(), metaInfo->getAuthor().c_str()); - auto linkInfo = PluginLinkInformationFactory::load(*pluginData, trampolineData, trampolineID++); + auto linkInfo = PluginLinkInformationFactory::load(*pluginDataWrapper.getPluginData(), trampolineData, trampolineID++); if (!linkInfo) { - auto errMsg = string_format("Failed to load plugin: %s", pluginData->getSource().c_str()); + auto errMsg = string_format("Failed to load plugin: %s", pluginDataWrapper.getPluginData()->getSource().c_str()); DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str()); DisplayErrorNotificationMessage(errMsg, 15.0f); continue; } - plugins.emplace_back(std::move(*metaInfo), std::move(*linkInfo), pluginData); + plugins.emplace_back(std::move(*metaInfo), std::move(*linkInfo), pluginDataWrapper.getPluginData()); } else { DEBUG_FUNCTION_LINE_INFO("We want to skip %s by %s", metaInfo->getName().c_str(), metaInfo->getAuthor().c_str()); - plugins.emplace_back(std::move(*metaInfo), PluginLinkInformation::CreateStub(), pluginData); + plugins.emplace_back(std::move(*metaInfo), PluginLinkInformation::CreateStub(), pluginDataWrapper.getPluginData()); } } else { - auto errMsg = string_format("Failed to load plugin: %s", pluginData->getSource().c_str()); + auto errMsg = string_format("Failed to load plugin: %s", *pluginDataWrapper.getPluginData()->getSource().c_str()); if (error == PLUGIN_PARSE_ERROR_INCOMPATIBLE_VERSION) { errMsg += ". Incompatible version."; } diff --git a/source/PluginManagement.h b/source/PluginManagement.h index f1b2d2c..2abd83e 100644 --- a/source/PluginManagement.h +++ b/source/PluginManagement.h @@ -1,6 +1,7 @@ #pragma once #include "plugin/PluginContainer.h" +#include "plugin/PluginLoadWrapper.h" #include #include #include @@ -10,7 +11,7 @@ class PluginManagement { public: static std::vector loadPlugins( - const std::set> &pluginDataList, + const std::vector &pluginDataList, std::vector &trampolineData); static void callInitHooks(const std::vector &plugins); diff --git a/source/globals.cpp b/source/globals.cpp index 7c16568..74cb9a8 100644 --- a/source/globals.cpp +++ b/source/globals.cpp @@ -7,7 +7,7 @@ std::vector gLoadedPlugins; std::vector gTrampData; std::set> gLoadedData; -std::set> gLoadOnNextLaunch; +std::vector gLoadOnNextLaunch; std::mutex gLoadedDataMutex; std::map gUsedRPLs; std::vector gAllocatedAddresses; diff --git a/source/globals.h b/source/globals.h index 7a5bba2..a10cdaa 100644 --- a/source/globals.h +++ b/source/globals.h @@ -1,5 +1,6 @@ #pragma once #include "plugin/PluginContainer.h" +#include "plugin/PluginLoadWrapper.h" #include "utils/config/ConfigUtils.h" #include "version.h" #include @@ -20,7 +21,7 @@ extern std::vector gTrampData; extern std::vector gLoadedPlugins; extern std::set> gLoadedData; -extern std::set> gLoadOnNextLaunch; +extern std::vector gLoadOnNextLaunch; extern std::mutex gLoadedDataMutex; extern std::map gUsedRPLs; extern std::vector gAllocatedAddresses; diff --git a/source/main.cpp b/source/main.cpp index 69a2860..9c5a87c 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -77,7 +77,8 @@ WUMS_APPLICATION_STARTS() { } OSReport("Running WiiUPluginLoaderBackend " VERSION_FULL "\n"); - gStoredTVBuffer = {}; + gStoredTVBuffer = {}; + gConfigMenuShouldClose = false; gUsedRPLs.clear(); diff --git a/source/patcher/hooks_patcher_static.cpp b/source/patcher/hooks_patcher_static.cpp index c7a8b5a..0e952a7 100644 --- a/source/patcher/hooks_patcher_static.cpp +++ b/source/patcher/hooks_patcher_static.cpp @@ -48,7 +48,7 @@ static uint32_t lastData0 = 0; DECL_FUNCTION(BOOL, OSSendMessage, OSMessageQueue *queue, OSMessage *message, OSMessageFlags flags) { if (sConfigMenuOpened && queue == OSGetSystemMessageQueue()) { if (message != nullptr) { - if (message->args[0] == 0xfacebacc) { // Release foreground + if (message->args[0] == 0xfacebacc && sConfigMenuOpened) { // Release foreground gConfigMenuShouldClose = true; } } diff --git a/source/plugin/PluginDataFactory.cpp b/source/plugin/PluginDataFactory.cpp index 61c84b7..84dd09d 100644 --- a/source/plugin/PluginDataFactory.cpp +++ b/source/plugin/PluginDataFactory.cpp @@ -16,6 +16,7 @@ ****************************************************************************/ #include "PluginDataFactory.h" #include "NotificationsUtils.h" +#include "PluginLoadWrapper.h" #include "fs/FSUtils.h" #include "utils/StringTools.h" #include "utils/logger.h" @@ -24,8 +25,8 @@ #include #include -std::set> PluginDataFactory::loadDir(std::string_view path) { - std::set> result; +std::vector PluginDataFactory::loadDir(std::string_view path) { + std::vector result; struct dirent *dp; DIR *dfd; @@ -52,7 +53,16 @@ std::set> PluginDataFactory::loadDir(std::string_vie DEBUG_FUNCTION_LINE("Loading plugin: %s", full_file_path.c_str()); auto pluginData = load(full_file_path); if (pluginData) { - result.insert(std::move(pluginData)); + // TODO: This is only for testing. Remove me!c + bool shouldBeLoadedAndLinked = false; + if (full_file_path.ends_with("AromaBasePlugin.wps") || + full_file_path.ends_with("drc_region_free.wps") || + full_file_path.ends_with("regionfree.wps") || + full_file_path.ends_with("ftpiiu.wps") || + full_file_path.ends_with("wiiload.wps")) { + shouldBeLoadedAndLinked = true; + } + result.emplace_back(std::move(pluginData), shouldBeLoadedAndLinked); } else { auto errMsg = string_format("Failed to load plugin: %s", full_file_path.c_str()); DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str()); diff --git a/source/plugin/PluginDataFactory.h b/source/plugin/PluginDataFactory.h index 205329b..88b808f 100644 --- a/source/plugin/PluginDataFactory.h +++ b/source/plugin/PluginDataFactory.h @@ -18,6 +18,7 @@ #pragma once #include "PluginData.h" +#include "PluginLoadWrapper.h" #include #include #include @@ -28,7 +29,7 @@ class PluginDataFactory { public: - static std::set> loadDir(std::string_view path); + static std::vector loadDir(std::string_view path); static std::unique_ptr load(std::string_view path); diff --git a/source/plugin/PluginLoadWrapper.h b/source/plugin/PluginLoadWrapper.h new file mode 100644 index 0000000..8834a4d --- /dev/null +++ b/source/plugin/PluginLoadWrapper.h @@ -0,0 +1,21 @@ +#pragma once +#include "PluginData.h" +#include + +class PluginLoadWrapper { +public: + PluginLoadWrapper(std::shared_ptr pluginData, bool linkAndLoad) : mPluginData(std::move(pluginData)), mIsLoadAndLink(linkAndLoad) { + } + + [[nodiscard]] const std::shared_ptr &getPluginData() const { + return mPluginData; + } + + [[nodiscard]] bool isLoadAndLink() const { + return mIsLoadAndLink; + } + +private: + std::shared_ptr mPluginData; + bool mIsLoadAndLink = false; +}; \ No newline at end of file diff --git a/source/utils/config/ConfigDisplayItem.h b/source/utils/config/ConfigDisplayItem.h index 9efefa6..ffa5e45 100644 --- a/source/utils/config/ConfigDisplayItem.h +++ b/source/utils/config/ConfigDisplayItem.h @@ -22,10 +22,14 @@ public: return *mConfig; } - [[nodiscard]] bool isActivePlugin () const { + [[nodiscard]] bool isActivePlugin() const { return mIsActivePlugin; - } + + void toggleIsActivePlugin() { + mIsActivePlugin = !mIsActivePlugin; + } + private: std::unique_ptr mConfig; GeneralConfigInformation mInfo; diff --git a/source/utils/config/ConfigRenderer.cpp b/source/utils/config/ConfigRenderer.cpp index 39a08b7..ed5a9d4 100644 --- a/source/utils/config/ConfigRenderer.cpp +++ b/source/utils/config/ConfigRenderer.cpp @@ -1,7 +1,10 @@ #include "ConfigRenderer.h" +#include +#include void ConfigRenderer::RenderStateMain() const { - auto totalElementSize = (int32_t) mActiveConfigs.size(); + auto &configs = GetConfigList(); + auto totalElementSize = (int32_t) configs.size(); // Calculate the range of items to display int start = std::max(0, mRenderOffset); int end = std::min(start + MAX_BUTTONS_ON_SCREEN, totalElementSize); @@ -11,7 +14,7 @@ void ConfigRenderer::RenderStateMain() const { uint32_t yOffset = 8 + 24 + 8 + 4; for (int32_t i = start; i < end; i++) { - drawConfigEntry(yOffset, mActiveConfigs[i].get().getConfigInformation(), i == mCursorPos); + drawConfigEntry(yOffset, configs[i].get().getConfigInformation(), i == mCursorPos, configs[i].get().isActivePlugin()); yOffset += 42 + 8; } @@ -19,7 +22,11 @@ void ConfigRenderer::RenderStateMain() const { // draw top bar DrawUtils::setFontSize(24); - DrawUtils::print(16, 6 + 24, "Wii U Plugin System Config Menu"); + if (mSetActivePluginsMode) { + DrawUtils::print(16, 6 + 24, "Please select the plugin that should be active"); + } else { + DrawUtils::print(16, 6 + 24, "Wii U Plugin System Config Menu"); + } DrawUtils::setFontSize(18); DrawUtils::print(SCREEN_WIDTH - 16, 8 + 24, VERSION_FULL, true); DrawUtils::drawRectFilled(8, 8 + 24 + 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK); @@ -28,7 +35,11 @@ void ConfigRenderer::RenderStateMain() const { DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK); DrawUtils::setFontSize(18); DrawUtils::print(16, SCREEN_HEIGHT - 10, "\ue07d Navigate "); - DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, "\ue000 Select", true); + if (mSetActivePluginsMode) { + DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, "\ue000 Select | \uE045 Apply", true); + } else { + DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, "\ue000 Activate", true); + } // draw scroll indicator DrawUtils::setFontSize(24); @@ -47,7 +58,7 @@ void ConfigRenderer::RenderStateMain() const { DrawUtils::endDraw(); } -void ConfigRenderer::drawConfigEntry(uint32_t yOffset, const GeneralConfigInformation &configInformation, bool isHighlighted) const { +void ConfigRenderer::drawConfigEntry(uint32_t yOffset, const GeneralConfigInformation &configInformation, bool isHighlighted, bool isActive) const { DrawUtils::setFontColor(COLOR_TEXT); if (isHighlighted) { @@ -56,41 +67,70 @@ void ConfigRenderer::drawConfigEntry(uint32_t yOffset, const GeneralConfigInform DrawUtils::drawRect(16, yOffset, SCREEN_WIDTH - 16 * 2, 44, 2, COLOR_BORDER); } + int textXOffset = 16 * 2; + if (mSetActivePluginsMode) { + DrawUtils::setFontSize(24); + if (isActive) { + DrawUtils::print(textXOffset, yOffset + 8 + 24, "x"); + } + textXOffset += 32; + } + DrawUtils::setFontSize(24); - DrawUtils::print(16 * 2, yOffset + 8 + 24, configInformation.name.c_str()); + DrawUtils::print(textXOffset, yOffset + 8 + 24, configInformation.name.c_str()); uint32_t sz = DrawUtils::getTextWidth(configInformation.name.c_str()); DrawUtils::setFontSize(12); - DrawUtils::print(16 * 2 + sz + 4, yOffset + 8 + 24, configInformation.author.c_str()); + DrawUtils::print(textXOffset + sz + 4, yOffset + 8 + 24, configInformation.author.c_str()); DrawUtils::print(SCREEN_WIDTH - 16 * 2, yOffset + 8 + 24, configInformation.version.c_str(), true); } ConfigSubState ConfigRenderer::UpdateStateMain(const Input &input) { - if (mActiveConfigs.empty()) { + auto &configs = GetConfigList(); + if (configs.empty()) { mNeedRedraw = true; return SUB_STATE_ERROR; } auto prevSelectedItem = mCursorPos; - auto totalElementSize = mActiveConfigs.size(); + auto totalElementSize = configs.size(); if (input.data.buttons_d & Input::eButtons::BUTTON_DOWN) { mCursorPos++; } else if (input.data.buttons_d & Input::eButtons::BUTTON_UP) { mCursorPos--; + } else if (input.data.buttons_d & Input::eButtons::BUTTON_PLUS) { + if (mSetActivePluginsMode) { + if (mActivePluginsDirty) { + for (const auto &cur : mConfigs) { + gLoadOnNextLaunch.emplace_back(cur.getConfigInformation().pluginData, cur.isActivePlugin()); + } + _SYSLaunchTitleWithStdArgsInNoSplash(OSGetTitleID(), nullptr); + } + mNeedRedraw = true; + mCategoryRenderer.reset(); + return SUB_STATE_RETURN; + } } else if (input.data.buttons_d & Input::eButtons::BUTTON_X) { mSetActivePluginsMode = !mSetActivePluginsMode; } else if (input.data.buttons_d & Input::eButtons::BUTTON_A) { - if (mCursorPos != mCurrentOpen) { - mCategoryRenderer.reset(); - mCategoryRenderer = make_unique_nothrow(&(mActiveConfigs[mCursorPos].get().getConfigInformation()), &(mActiveConfigs[mCursorPos].get().getConfig()), true); + if (mSetActivePluginsMode) { + mActivePluginsDirty = true; + mNeedRedraw = true; + configs[mCursorPos].get().toggleIsActivePlugin(); + return SUB_STATE_RUNNING; + } else { + if (mCursorPos != mCurrentOpen) { + mCategoryRenderer.reset(); + mCategoryRenderer = make_unique_nothrow(&(configs[mCursorPos].get().getConfigInformation()), &(configs[mCursorPos].get().getConfig()), true); + } + mNeedRedraw = true; + mCurrentOpen = mCursorPos; + mState = STATE_SUB; + return SUB_STATE_RUNNING; } - mNeedRedraw = true; - mCurrentOpen = mCursorPos; - mState = STATE_SUB; - return SUB_STATE_RUNNING; } else if (input.data.buttons_d & (Input::eButtons::BUTTON_B | Input::eButtons::BUTTON_HOME)) { mNeedRedraw = true; mCategoryRenderer.reset(); - for (const auto &element : mActiveConfigs) { + for (const auto &element : configs) { CallOnCloseCallback(element.get().getConfigInformation(), element.get().getConfig()); } return SUB_STATE_RETURN; diff --git a/source/utils/config/ConfigRenderer.h b/source/utils/config/ConfigRenderer.h index 5e69bd2..65ce773 100644 --- a/source/utils/config/ConfigRenderer.h +++ b/source/utils/config/ConfigRenderer.h @@ -11,9 +11,11 @@ class ConfigRenderer { public: explicit ConfigRenderer(std::vector &&vec) : mConfigs(std::move(vec)) { + std::copy(mConfigs.begin(), mConfigs.end(), + std::back_inserter(mAllConfigs)); std::copy_if(mConfigs.begin(), mConfigs.end(), std::back_inserter(mActiveConfigs), - [&](const auto & value) { + [&](const auto &value) { return value.isActivePlugin(); }); } @@ -33,7 +35,14 @@ private: void RenderStateMain() const; - void drawConfigEntry(uint32_t yOffset, const GeneralConfigInformation &configInformation, bool isHighlighted) const; + [[nodiscard]] const std::vector> &GetConfigList() const { + if (mSetActivePluginsMode) { + return mAllConfigs; + } + return mActiveConfigs; + } + + void drawConfigEntry(uint32_t yOffset, const GeneralConfigInformation &configInformation, bool isHighlighted, bool isActive) const; enum State { STATE_MAIN = 0, @@ -41,6 +50,7 @@ private: }; std::vector mConfigs; + std::vector> mAllConfigs; std::vector> mActiveConfigs; std::unique_ptr mCategoryRenderer = {}; @@ -52,5 +62,7 @@ private: void CallOnCloseCallback(const GeneralConfigInformation &info, const std::vector> &categories); void CallOnCloseCallback(const GeneralConfigInformation &info, const WUPSConfigAPIBackend::WUPSConfig &config); - bool mNeedRedraw = true; + bool mNeedRedraw = true; + bool mSetActivePluginsMode = false; + bool mActivePluginsDirty = false; }; diff --git a/source/utils/config/ConfigUtils.cpp b/source/utils/config/ConfigUtils.cpp index 45cfa1c..dcbd088 100644 --- a/source/utils/config/ConfigUtils.cpp +++ b/source/utils/config/ConfigUtils.cpp @@ -125,6 +125,7 @@ void ConfigUtils::displayMenu() { if (!config) { config = make_unique_nothrow(info.name); } + configs.emplace_back(info, std::move(config), plugin.isLinkedAndLoaded()); } diff --git a/source/utils/exports.cpp b/source/utils/exports.cpp index 1ae4949..8e9c390 100644 --- a/source/utils/exports.cpp +++ b/source/utils/exports.cpp @@ -30,7 +30,7 @@ extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const wups_back for (const auto &pluginData : gLoadedData) { if (pluginData->getHandle() == handle) { - gLoadOnNextLaunch.insert(pluginData); + gLoadOnNextLaunch.emplace_back(pluginData, true); found = true; break; }