mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2024-12-23 19:41:49 +01:00
Initial support for disabling/enabling plugins in config menu
This commit is contained in:
parent
9e0932cb38
commit
8be76541cd
@ -3,6 +3,7 @@
|
|||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
#include "plugin/PluginContainer.h"
|
#include "plugin/PluginContainer.h"
|
||||||
#include "plugin/PluginLinkInformationFactory.h"
|
#include "plugin/PluginLinkInformationFactory.h"
|
||||||
|
#include "plugin/PluginLoadWrapper.h"
|
||||||
#include "plugin/PluginMetaInformationFactory.h"
|
#include "plugin/PluginMetaInformationFactory.h"
|
||||||
#include "utils/ElfUtils.h"
|
#include "utils/ElfUtils.h"
|
||||||
#include "utils/StringTools.h"
|
#include "utils/StringTools.h"
|
||||||
@ -10,49 +11,35 @@
|
|||||||
#include <coreinit/cache.h>
|
#include <coreinit/cache.h>
|
||||||
#include <coreinit/dynload.h>
|
#include <coreinit/dynload.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <memory>
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
static uint32_t sTrampolineID = 0;
|
static uint32_t sTrampolineID = 0;
|
||||||
|
|
||||||
bool CheckIfAllowed(const PluginMetaInformation &metaInfo) {
|
|
||||||
std::vector<std::pair<std::string, std::string>> 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<PluginContainer>
|
std::vector<PluginContainer>
|
||||||
PluginManagement::loadPlugins(const std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> &pluginDataList, std::vector<relocation_trampoline_entry_t> &trampolineData) {
|
PluginManagement::loadPlugins(const std::vector<PluginLoadWrapper> &pluginDataList, std::vector<relocation_trampoline_entry_t> &trampolineData) {
|
||||||
std::vector<PluginContainer> plugins;
|
std::vector<PluginContainer> plugins;
|
||||||
|
|
||||||
for (const auto &pluginData : pluginDataList) {
|
for (const auto &pluginDataWrapper : pluginDataList) {
|
||||||
PluginParseErrors error = PLUGIN_PARSE_ERROR_UNKNOWN;
|
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 (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());
|
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, sTrampolineID++);
|
|
||||||
|
auto linkInfo = PluginLinkInformationFactory::load(*pluginDataWrapper.getPluginData(), trampolineData, sTrampolineID++);
|
||||||
if (!linkInfo) {
|
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());
|
DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str());
|
||||||
DisplayErrorNotificationMessage(errMsg, 15.0f);
|
DisplayErrorNotificationMessage(errMsg, 15.0f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
plugins.emplace_back(std::move(*metaInfo), std::move(*linkInfo), pluginData);
|
plugins.emplace_back(std::move(*metaInfo), std::move(*linkInfo), pluginDataWrapper.getPluginData());
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE_INFO("We want to skip %s by %s", metaInfo->getName().c_str(), metaInfo->getAuthor().c_str());
|
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 {
|
} 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) {
|
if (error == PLUGIN_PARSE_ERROR_INCOMPATIBLE_VERSION) {
|
||||||
errMsg += ". Incompatible version.";
|
errMsg += ". Incompatible version.";
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "plugin/PluginContainer.h"
|
#include "plugin/PluginContainer.h"
|
||||||
|
#include "plugin/PluginLoadWrapper.h"
|
||||||
#include <coreinit/dynload.h>
|
#include <coreinit/dynload.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <wums/defines/relocation_defines.h>
|
#include <wums/defines/relocation_defines.h>
|
||||||
|
|
||||||
class PluginManagement {
|
class PluginManagement {
|
||||||
public:
|
public:
|
||||||
static std::vector<PluginContainer> loadPlugins(
|
static std::vector<PluginContainer> loadPlugins(
|
||||||
const std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> &pluginDataList,
|
const std::vector<PluginLoadWrapper> &pluginDataList,
|
||||||
std::vector<relocation_trampoline_entry_t> &trampolineData);
|
std::vector<relocation_trampoline_entry_t> &trampolineData);
|
||||||
|
|
||||||
static void callInitHooks(const std::vector<PluginContainer> &plugins, const std::function<bool(const PluginContainer &)> &pred);
|
static void callInitHooks(const std::vector<PluginContainer> &plugins, const std::function<bool(const PluginContainer &)> &pred);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "plugin/PluginContainer.h"
|
#include "plugin/PluginContainer.h"
|
||||||
#include "plugin/PluginData.h"
|
#include "plugin/PluginData.h"
|
||||||
|
#include "plugin/PluginLoadWrapper.h"
|
||||||
|
|
||||||
StoredBuffer gStoredTVBuffer = {};
|
StoredBuffer gStoredTVBuffer = {};
|
||||||
StoredBuffer gStoredDRCBuffer = {};
|
StoredBuffer gStoredDRCBuffer = {};
|
||||||
@ -9,7 +10,7 @@ std::vector<PluginContainer> gLoadedPlugins;
|
|||||||
std::vector<relocation_trampoline_entry_t> gTrampData;
|
std::vector<relocation_trampoline_entry_t> gTrampData;
|
||||||
|
|
||||||
std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> gLoadedData;
|
std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> gLoadedData;
|
||||||
std::vector<std::shared_ptr<PluginData>> gLoadOnNextLaunch;
|
std::vector<PluginLoadWrapper> gLoadOnNextLaunch;
|
||||||
std::mutex gLoadedDataMutex;
|
std::mutex gLoadedDataMutex;
|
||||||
std::map<std::string, OSDynLoad_Module> gUsedRPLs;
|
std::map<std::string, OSDynLoad_Module> gUsedRPLs;
|
||||||
std::vector<void *> gAllocatedAddresses;
|
std::vector<void *> gAllocatedAddresses;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
class PluginDataSharedPtrComparator;
|
class PluginDataSharedPtrComparator;
|
||||||
class PluginData;
|
class PluginData;
|
||||||
class PluginContainer;
|
class PluginContainer;
|
||||||
|
class PluginLoadWrapper;
|
||||||
|
|
||||||
extern StoredBuffer gStoredTVBuffer;
|
extern StoredBuffer gStoredTVBuffer;
|
||||||
extern StoredBuffer gStoredDRCBuffer;
|
extern StoredBuffer gStoredDRCBuffer;
|
||||||
@ -25,7 +26,7 @@ extern std::vector<relocation_trampoline_entry_t> gTrampData;
|
|||||||
extern std::vector<PluginContainer> gLoadedPlugins;
|
extern std::vector<PluginContainer> gLoadedPlugins;
|
||||||
|
|
||||||
extern std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> gLoadedData;
|
extern std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> gLoadedData;
|
||||||
extern std::vector<std::shared_ptr<PluginData>> gLoadOnNextLaunch;
|
extern std::vector<PluginLoadWrapper> gLoadOnNextLaunch;
|
||||||
extern std::mutex gLoadedDataMutex;
|
extern std::mutex gLoadedDataMutex;
|
||||||
extern std::map<std::string, OSDynLoad_Module> gUsedRPLs;
|
extern std::map<std::string, OSDynLoad_Module> gUsedRPLs;
|
||||||
extern std::vector<void *> gAllocatedAddresses;
|
extern std::vector<void *> gAllocatedAddresses;
|
||||||
|
@ -81,7 +81,8 @@ WUMS_APPLICATION_STARTS() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OSReport("Running WiiUPluginLoaderBackend " MODULE_VERSION_FULL "\n");
|
OSReport("Running WiiUPluginLoaderBackend " MODULE_VERSION_FULL "\n");
|
||||||
gStoredTVBuffer = {};
|
gStoredTVBuffer = {};
|
||||||
|
gConfigMenuShouldClose = false;
|
||||||
|
|
||||||
gUsedRPLs.clear();
|
gUsedRPLs.clear();
|
||||||
|
|
||||||
@ -117,21 +118,21 @@ WUMS_APPLICATION_STARTS() {
|
|||||||
|
|
||||||
if (!gLoadOnNextLaunch.empty()) {
|
if (!gLoadOnNextLaunch.empty()) {
|
||||||
std::vector<PluginContainer> pluginsToKeep;
|
std::vector<PluginContainer> pluginsToKeep;
|
||||||
std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> toBeLoaded;
|
std::vector<PluginLoadWrapper> toBeLoaded;
|
||||||
|
|
||||||
// Check which plugins are already loaded and which needs to be
|
// Check which plugins are already loaded and which needs to be
|
||||||
for (const auto &pluginData : gLoadOnNextLaunch) {
|
for (const auto &pluginLoadWrapper : gLoadOnNextLaunch) {
|
||||||
// Check if the plugin data is already loaded
|
// Check if the plugin data is already loaded
|
||||||
if (auto it = std::ranges::find_if(gLoadedPlugins,
|
if (auto it = std::ranges::find_if(gLoadedPlugins,
|
||||||
[&pluginData](const PluginContainer &container) {
|
[&pluginLoadWrapper](const PluginContainer &container) {
|
||||||
return container.getPluginDataCopy()->getHandle() == pluginData->getHandle();
|
return container.getPluginDataCopy()->getHandle() == pluginLoadWrapper.getPluginData()->getHandle();
|
||||||
});
|
});
|
||||||
it != gLoadedPlugins.end()) {
|
it != gLoadedPlugins.end()) {
|
||||||
pluginsToKeep.push_back(std::move(*it));
|
pluginsToKeep.push_back(std::move(*it));
|
||||||
gLoadedPlugins.erase(it);
|
gLoadedPlugins.erase(it);
|
||||||
} else {
|
} else {
|
||||||
// Load it if it's not already loaded
|
// Load it if it's not already loaded
|
||||||
toBeLoaded.insert(pluginData);
|
toBeLoaded.push_back(pluginLoadWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ static uint32_t lastData0 = 0;
|
|||||||
DECL_FUNCTION(BOOL, OSSendMessage, OSMessageQueue *queue, OSMessage *message, OSMessageFlags flags) {
|
DECL_FUNCTION(BOOL, OSSendMessage, OSMessageQueue *queue, OSMessage *message, OSMessageFlags flags) {
|
||||||
if (sConfigMenuOpened && queue == OSGetSystemMessageQueue()) {
|
if (sConfigMenuOpened && queue == OSGetSystemMessageQueue()) {
|
||||||
if (message != nullptr) {
|
if (message != nullptr) {
|
||||||
if (message->args[0] == 0xfacebacc) { // Release foreground
|
if (message->args[0] == 0xfacebacc && sConfigMenuOpened) { // Release foreground
|
||||||
gConfigMenuShouldClose = true;
|
gConfigMenuShouldClose = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "PluginDataFactory.h"
|
#include "PluginDataFactory.h"
|
||||||
#include "NotificationsUtils.h"
|
#include "NotificationsUtils.h"
|
||||||
|
#include "PluginLoadWrapper.h"
|
||||||
#include "fs/FSUtils.h"
|
#include "fs/FSUtils.h"
|
||||||
#include "utils/StringTools.h"
|
#include "utils/StringTools.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
@ -25,8 +26,8 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <sys/dirent.h>
|
#include <sys/dirent.h>
|
||||||
|
|
||||||
std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> PluginDataFactory::loadDir(const std::string_view path) {
|
std::vector<PluginLoadWrapper> PluginDataFactory::loadDir(std::string_view path) {
|
||||||
std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> result;
|
std::vector<PluginLoadWrapper> result;
|
||||||
dirent *dp;
|
dirent *dp;
|
||||||
DIR *dfd;
|
DIR *dfd;
|
||||||
|
|
||||||
@ -51,8 +52,18 @@ std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> PluginDataF
|
|||||||
|
|
||||||
auto full_file_path = string_format("%s/%s", path.data(), dp->d_name);
|
auto full_file_path = string_format("%s/%s", path.data(), dp->d_name);
|
||||||
DEBUG_FUNCTION_LINE("Loading plugin: %s", full_file_path.c_str());
|
DEBUG_FUNCTION_LINE("Loading plugin: %s", full_file_path.c_str());
|
||||||
|
|
||||||
if (auto pluginData = load(full_file_path)) {
|
if (auto pluginData = load(full_file_path)) {
|
||||||
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 {
|
} else {
|
||||||
auto errMsg = string_format("Failed to load plugin: %s", full_file_path.c_str());
|
auto errMsg = string_format("Failed to load plugin: %s", full_file_path.c_str());
|
||||||
DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str());
|
DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str());
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "PluginData.h"
|
#include "PluginData.h"
|
||||||
|
#include "PluginLoadWrapper.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -24,7 +25,7 @@
|
|||||||
|
|
||||||
class PluginDataFactory {
|
class PluginDataFactory {
|
||||||
public:
|
public:
|
||||||
static std::set<std::shared_ptr<PluginData>, PluginDataSharedPtrComparator> loadDir(std::string_view path);
|
static std::vector<PluginLoadWrapper> loadDir(std::string_view path);
|
||||||
|
|
||||||
static std::unique_ptr<PluginData> load(std::string_view path);
|
static std::unique_ptr<PluginData> load(std::string_view path);
|
||||||
|
|
||||||
|
21
source/plugin/PluginLoadWrapper.h
Normal file
21
source/plugin/PluginLoadWrapper.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "PluginData.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class PluginLoadWrapper {
|
||||||
|
public:
|
||||||
|
PluginLoadWrapper(std::shared_ptr<PluginData> pluginData, const bool linkAndLoad) : mPluginData(std::move(pluginData)), mIsLoadAndLink(linkAndLoad) {
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const std::shared_ptr<PluginData> &getPluginData() const {
|
||||||
|
return mPluginData;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isLoadAndLink() const {
|
||||||
|
return mIsLoadAndLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<PluginData> mPluginData;
|
||||||
|
bool mIsLoadAndLink = false;
|
||||||
|
};
|
@ -20,3 +20,7 @@ const WUPSConfigAPIBackend::WUPSConfig &ConfigDisplayItem::getConfig() const {
|
|||||||
bool ConfigDisplayItem::isActivePlugin() const {
|
bool ConfigDisplayItem::isActivePlugin() const {
|
||||||
return mIsActivePlugin;
|
return mIsActivePlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigDisplayItem::toggleIsActivePlugin() {
|
||||||
|
mIsActivePlugin = !mIsActivePlugin;
|
||||||
|
}
|
@ -22,6 +22,8 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] bool isActivePlugin() const;
|
[[nodiscard]] bool isActivePlugin() const;
|
||||||
|
|
||||||
|
void toggleIsActivePlugin();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<WUPSConfigAPIBackend::WUPSConfig> mConfig;
|
std::unique_ptr<WUPSConfigAPIBackend::WUPSConfig> mConfig;
|
||||||
GeneralConfigInformation mInfo;
|
GeneralConfigInformation mInfo;
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
#include "ConfigRenderer.h"
|
#include "ConfigRenderer.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
#include "plugin/PluginLoadWrapper.h"
|
||||||
#include "utils/DrawUtils.h"
|
#include "utils/DrawUtils.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
|
||||||
|
#include <coreinit/title.h>
|
||||||
|
#include <sysapp/launch.h>
|
||||||
|
|
||||||
ConfigRenderer::ConfigRenderer(std::vector<ConfigDisplayItem> &&vec) : mConfigs(std::move(vec)) {
|
ConfigRenderer::ConfigRenderer(std::vector<ConfigDisplayItem> &&vec) : mConfigs(std::move(vec)) {
|
||||||
|
std::copy(mConfigs.begin(), mConfigs.end(),
|
||||||
|
std::back_inserter(mAllConfigs));
|
||||||
std::copy_if(mConfigs.begin(), mConfigs.end(),
|
std::copy_if(mConfigs.begin(), mConfigs.end(),
|
||||||
std::back_inserter(mActiveConfigs),
|
std::back_inserter(mActiveConfigs),
|
||||||
[&](const auto &value) {
|
[&](const auto &value) {
|
||||||
@ -20,7 +26,8 @@ ConfigSubState ConfigRenderer::Update(Input &input, const WUPSConfigSimplePadDat
|
|||||||
return UpdateStateMain(input);
|
return UpdateStateMain(input);
|
||||||
case STATE_SUB: {
|
case STATE_SUB: {
|
||||||
if (mCategoryRenderer) {
|
if (mCategoryRenderer) {
|
||||||
if (const auto subResult = mCategoryRenderer->Update(input, simpleInputData, complexInputData); subResult != SUB_STATE_RUNNING) {
|
auto subResult = mCategoryRenderer->Update(input, simpleInputData, complexInputData);
|
||||||
|
if (subResult != SUB_STATE_RUNNING) {
|
||||||
mNeedRedraw = true;
|
mNeedRedraw = true;
|
||||||
mState = STATE_MAIN;
|
mState = STATE_MAIN;
|
||||||
return SUB_STATE_RUNNING;
|
return SUB_STATE_RUNNING;
|
||||||
@ -55,8 +62,7 @@ void ConfigRenderer::Render() const {
|
|||||||
bool ConfigRenderer::NeedsRedraw() const {
|
bool ConfigRenderer::NeedsRedraw() const {
|
||||||
if (mNeedRedraw) {
|
if (mNeedRedraw) {
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if (mCategoryRenderer) {
|
||||||
if (mCategoryRenderer) {
|
|
||||||
return mCategoryRenderer->NeedsRedraw();
|
return mCategoryRenderer->NeedsRedraw();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -70,52 +76,60 @@ void ConfigRenderer::ResetNeedsRedraw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConfigSubState ConfigRenderer::UpdateStateMain(const Input &input) {
|
ConfigSubState ConfigRenderer::UpdateStateMain(const Input &input) {
|
||||||
if (mActiveConfigs.empty()) {
|
auto &configs = GetConfigList();
|
||||||
|
if (configs.empty()) {
|
||||||
mNeedRedraw = true;
|
mNeedRedraw = true;
|
||||||
return SUB_STATE_ERROR;
|
return SUB_STATE_ERROR;
|
||||||
}
|
}
|
||||||
const auto prevSelectedItem = mCursorPos;
|
auto prevSelectedItem = mCursorPos;
|
||||||
|
|
||||||
const auto totalElementSize = mActiveConfigs.size();
|
auto totalElementSize = configs.size();
|
||||||
if (input.data.buttons_d & Input::eButtons::BUTTON_DOWN) {
|
if (input.data.buttons_d & Input::eButtons::BUTTON_DOWN) {
|
||||||
mCursorPos++;
|
mCursorPos++;
|
||||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_LEFT) {
|
|
||||||
// Paging up
|
|
||||||
mCursorPos -= MAX_BUTTONS_ON_SCREEN - 1;
|
|
||||||
// Don't jump past the top
|
|
||||||
if (mCursorPos < 0)
|
|
||||||
mCursorPos = 0;
|
|
||||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_RIGHT) {
|
|
||||||
// Paging down
|
|
||||||
mCursorPos += MAX_BUTTONS_ON_SCREEN - 1;
|
|
||||||
// Don't jump past the bottom
|
|
||||||
if (mCursorPos >= totalElementSize)
|
|
||||||
mCursorPos = totalElementSize - 1;
|
|
||||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_UP) {
|
} else if (input.data.buttons_d & Input::eButtons::BUTTON_UP) {
|
||||||
mCursorPos--;
|
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) {
|
} else if (input.data.buttons_d & Input::eButtons::BUTTON_X) {
|
||||||
mSetActivePluginsMode = !mSetActivePluginsMode;
|
mSetActivePluginsMode = !mSetActivePluginsMode;
|
||||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_A) {
|
} else if (input.data.buttons_d & Input::eButtons::BUTTON_A) {
|
||||||
if (mCursorPos != mCurrentOpen) {
|
if (mSetActivePluginsMode) {
|
||||||
mCategoryRenderer.reset();
|
mActivePluginsDirty = true;
|
||||||
mCategoryRenderer = make_unique_nothrow<CategoryRenderer>(&(mActiveConfigs[mCursorPos].get().getConfigInformation()), &(mActiveConfigs[mCursorPos].get().getConfig()), true);
|
mNeedRedraw = true;
|
||||||
|
configs[mCursorPos].get().toggleIsActivePlugin();
|
||||||
|
return SUB_STATE_RUNNING;
|
||||||
|
} else {
|
||||||
|
if (mCursorPos != mCurrentOpen) {
|
||||||
|
mCategoryRenderer.reset();
|
||||||
|
mCategoryRenderer = make_unique_nothrow<CategoryRenderer>(&(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)) {
|
} else if (input.data.buttons_d & (Input::eButtons::BUTTON_B | Input::eButtons::BUTTON_HOME)) {
|
||||||
mNeedRedraw = true;
|
mNeedRedraw = true;
|
||||||
mCategoryRenderer.reset();
|
mCategoryRenderer.reset();
|
||||||
for (const auto &element : mActiveConfigs) {
|
for (const auto &element : configs) {
|
||||||
CallOnCloseCallback(element.get().getConfigInformation(), element.get().getConfig());
|
CallOnCloseCallback(element.get().getConfigInformation(), element.get().getConfig());
|
||||||
}
|
}
|
||||||
return SUB_STATE_RETURN;
|
return SUB_STATE_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCursorPos < 0) {
|
if (mCursorPos < 0) {
|
||||||
mCursorPos = totalElementSize - 1;
|
mCursorPos = (int32_t) totalElementSize - 1;
|
||||||
} else if (mCursorPos > totalElementSize - 1) {
|
} else if (mCursorPos > (int32_t) (totalElementSize - 1)) {
|
||||||
mCursorPos = 0;
|
mCursorPos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,9 +147,9 @@ ConfigSubState ConfigRenderer::UpdateStateMain(const Input &input) {
|
|||||||
return SUB_STATE_RUNNING;
|
return SUB_STATE_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ConfigRenderer::RenderStateMain() const {
|
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
|
// Calculate the range of items to display
|
||||||
int start = std::max(0, mRenderOffset);
|
int start = std::max(0, mRenderOffset);
|
||||||
int end = std::min(start + MAX_BUTTONS_ON_SCREEN, totalElementSize);
|
int end = std::min(start + MAX_BUTTONS_ON_SCREEN, totalElementSize);
|
||||||
@ -145,7 +159,7 @@ void ConfigRenderer::RenderStateMain() const {
|
|||||||
|
|
||||||
uint32_t yOffset = 8 + 24 + 8 + 4;
|
uint32_t yOffset = 8 + 24 + 8 + 4;
|
||||||
for (int32_t i = start; i < end; i++) {
|
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;
|
yOffset += 42 + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +167,11 @@ void ConfigRenderer::RenderStateMain() const {
|
|||||||
|
|
||||||
// draw top bar
|
// draw top bar
|
||||||
DrawUtils::setFontSize(24);
|
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::setFontSize(18);
|
||||||
DrawUtils::print(SCREEN_WIDTH - 16, 8 + 24, MODULE_VERSION_FULL, true);
|
DrawUtils::print(SCREEN_WIDTH - 16, 8 + 24, MODULE_VERSION_FULL, true);
|
||||||
DrawUtils::drawRectFilled(8, 8 + 24 + 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK);
|
DrawUtils::drawRectFilled(8, 8 + 24 + 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK);
|
||||||
@ -162,7 +180,11 @@ void ConfigRenderer::RenderStateMain() const {
|
|||||||
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK);
|
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK);
|
||||||
DrawUtils::setFontSize(18);
|
DrawUtils::setFontSize(18);
|
||||||
DrawUtils::print(16, SCREEN_HEIGHT - 10, "\ue07d Navigate ");
|
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
|
// draw scroll indicator
|
||||||
DrawUtils::setFontSize(24);
|
DrawUtils::setFontSize(24);
|
||||||
@ -181,7 +203,7 @@ void ConfigRenderer::RenderStateMain() const {
|
|||||||
DrawUtils::endDraw();
|
DrawUtils::endDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigRenderer::DrawConfigEntry(const uint32_t yOffset, const GeneralConfigInformation &configInformation, const bool isHighlighted) const {
|
void ConfigRenderer::DrawConfigEntry(uint32_t yOffset, const GeneralConfigInformation &configInformation, bool isHighlighted, bool isActive) const {
|
||||||
DrawUtils::setFontColor(COLOR_TEXT);
|
DrawUtils::setFontColor(COLOR_TEXT);
|
||||||
|
|
||||||
if (isHighlighted) {
|
if (isHighlighted) {
|
||||||
@ -190,11 +212,21 @@ void ConfigRenderer::DrawConfigEntry(const uint32_t yOffset, const GeneralConfig
|
|||||||
DrawUtils::drawRect(16, yOffset, SCREEN_WIDTH - 16 * 2, 44, 2, COLOR_BORDER);
|
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::setFontSize(24);
|
||||||
DrawUtils::print(16 * 2, yOffset + 8 + 24, configInformation.name.c_str());
|
|
||||||
const uint32_t sz = DrawUtils::getTextWidth(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::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);
|
DrawUtils::print(SCREEN_WIDTH - 16 * 2, yOffset + 8 + 24, configInformation.version.c_str(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,3 +247,10 @@ void ConfigRenderer::CallOnCloseCallback(const GeneralConfigInformation &info, c
|
|||||||
item->onCloseCallback();
|
item->onCloseCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<std::reference_wrapper<ConfigDisplayItem>> &ConfigRenderer::GetConfigList() const {
|
||||||
|
if (mSetActivePluginsMode) {
|
||||||
|
return mAllConfigs;
|
||||||
|
}
|
||||||
|
return mActiveConfigs;
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
#include <wups/config.h>
|
#include <wups/config.h>
|
||||||
|
|
||||||
class ConfigRenderer {
|
class ConfigRenderer {
|
||||||
@ -30,17 +31,20 @@ private:
|
|||||||
|
|
||||||
void RenderStateMain() const;
|
void RenderStateMain() const;
|
||||||
|
|
||||||
void DrawConfigEntry(uint32_t yOffset, const GeneralConfigInformation &configInformation, bool isHighlighted) const;
|
void DrawConfigEntry(uint32_t yOffset, const GeneralConfigInformation &configInformation, bool isHighlighted, bool isActive) const;
|
||||||
|
|
||||||
void CallOnCloseCallback(const GeneralConfigInformation &info, const std::vector<std::unique_ptr<WUPSConfigAPIBackend::WUPSConfigCategory>> &categories);
|
void CallOnCloseCallback(const GeneralConfigInformation &info, const std::vector<std::unique_ptr<WUPSConfigAPIBackend::WUPSConfigCategory>> &categories);
|
||||||
void CallOnCloseCallback(const GeneralConfigInformation &info, const WUPSConfigAPIBackend::WUPSConfig &config);
|
void CallOnCloseCallback(const GeneralConfigInformation &info, const WUPSConfigAPIBackend::WUPSConfig &config);
|
||||||
|
|
||||||
|
const std::vector<std::reference_wrapper<ConfigDisplayItem>> &GetConfigList() const;
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
STATE_MAIN = 0,
|
STATE_MAIN = 0,
|
||||||
STATE_SUB = 1,
|
STATE_SUB = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<ConfigDisplayItem> mConfigs;
|
std::vector<ConfigDisplayItem> mConfigs;
|
||||||
|
std::vector<std::reference_wrapper<ConfigDisplayItem>> mAllConfigs;
|
||||||
std::vector<std::reference_wrapper<ConfigDisplayItem>> mActiveConfigs;
|
std::vector<std::reference_wrapper<ConfigDisplayItem>> mActiveConfigs;
|
||||||
std::unique_ptr<CategoryRenderer> mCategoryRenderer = {};
|
std::unique_ptr<CategoryRenderer> mCategoryRenderer = {};
|
||||||
|
|
||||||
@ -50,6 +54,7 @@ private:
|
|||||||
int32_t mRenderOffset = 0;
|
int32_t mRenderOffset = 0;
|
||||||
int32_t mCurrentOpen = -1;
|
int32_t mCurrentOpen = -1;
|
||||||
|
|
||||||
bool mSetActivePluginsMode = false;
|
|
||||||
bool mNeedRedraw = true;
|
bool mNeedRedraw = true;
|
||||||
|
bool mSetActivePluginsMode = false;
|
||||||
|
bool mActivePluginsDirty = false;
|
||||||
};
|
};
|
||||||
|
@ -125,6 +125,7 @@ void ConfigUtils::displayMenu() {
|
|||||||
if (!config) {
|
if (!config) {
|
||||||
config = make_unique_nothrow<WUPSConfigAPIBackend::WUPSConfig>(info.name);
|
config = make_unique_nothrow<WUPSConfigAPIBackend::WUPSConfig>(info.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
configs.emplace_back(info, std::move(config), plugin.isLinkedAndLoaded());
|
configs.emplace_back(info, std::move(config), plugin.isLinkedAndLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const wups_back
|
|||||||
|
|
||||||
for (const auto &pluginData : gLoadedData) {
|
for (const auto &pluginData : gLoadedData) {
|
||||||
if (pluginData->getHandle() == handle) {
|
if (pluginData->getHandle() == handle) {
|
||||||
gLoadOnNextLaunch.push_back(pluginData);
|
gLoadOnNextLaunch.emplace_back(pluginData, true);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user