mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2025-01-09 19:19:21 +01:00
Add initial support for persisting a lsit inactive plugins
This commit is contained in:
parent
fa54b63f64
commit
ab8c36b855
@ -5,6 +5,7 @@
|
|||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
#include "patcher/hooks_patcher_static.h"
|
#include "patcher/hooks_patcher_static.h"
|
||||||
#include "plugin/PluginDataFactory.h"
|
#include "plugin/PluginDataFactory.h"
|
||||||
|
#include "utils/WUPSBackendSettings.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@ -112,7 +113,9 @@ WUMS_APPLICATION_STARTS() {
|
|||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Load plugins from %s", pluginPath.c_str());
|
DEBUG_FUNCTION_LINE("Load plugins from %s", pluginPath.c_str());
|
||||||
|
|
||||||
const auto pluginData = PluginDataFactory::loadDir(pluginPath);
|
WUPSBackendSettings::LoadSettings();
|
||||||
|
auto &inactiveList = WUPSBackendSettings::GetInactivePluginFilenames();
|
||||||
|
const auto pluginData = PluginDataFactory::loadDir(pluginPath, inactiveList);
|
||||||
newLoadedPlugins = PluginManagement::loadPlugins(pluginData, gTrampData);
|
newLoadedPlugins = PluginManagement::loadPlugins(pluginData, gTrampData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <sys/dirent.h>
|
#include <sys/dirent.h>
|
||||||
|
|
||||||
std::vector<PluginLoadWrapper> PluginDataFactory::loadDir(std::string_view path) {
|
|
||||||
|
std::vector<PluginLoadWrapper> PluginDataFactory::loadDir(std::string_view path, const std::vector<std::string> &inactivePluginsFilenames) {
|
||||||
std::vector<PluginLoadWrapper> result;
|
std::vector<PluginLoadWrapper> result;
|
||||||
dirent *dp;
|
dirent *dp;
|
||||||
DIR *dfd;
|
DIR *dfd;
|
||||||
@ -54,15 +55,9 @@ std::vector<PluginLoadWrapper> PluginDataFactory::loadDir(std::string_view path)
|
|||||||
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)) {
|
||||||
// TODO: This is only for testing. Remove me!c
|
bool shouldBeLoadedAndLinked = true;
|
||||||
bool shouldBeLoadedAndLinked = false;
|
if (std::ranges::find(inactivePluginsFilenames, dp->d_name) != inactivePluginsFilenames.end()) {
|
||||||
if (full_file_path.ends_with("AromaBasePlugin.wps") ||
|
shouldBeLoadedAndLinked = false;
|
||||||
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") ||
|
|
||||||
full_file_path.ends_with("homebrew_on_menu.wps")) {
|
|
||||||
shouldBeLoadedAndLinked = true;
|
|
||||||
}
|
}
|
||||||
result.emplace_back(std::move(pluginData), shouldBeLoadedAndLinked);
|
result.emplace_back(std::move(pluginData), shouldBeLoadedAndLinked);
|
||||||
} else {
|
} else {
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
class PluginDataFactory {
|
class PluginDataFactory {
|
||||||
public:
|
public:
|
||||||
static std::vector<PluginLoadWrapper> loadDir(std::string_view path);
|
static std::vector<PluginLoadWrapper> loadDir(std::string_view path, const std::vector<std::string> &inactivePluginsFilenames);
|
||||||
|
|
||||||
static std::unique_ptr<PluginData> load(std::string_view path);
|
static std::unique_ptr<PluginData> load(std::string_view path);
|
||||||
|
|
||||||
|
77
source/utils/WUPSBackendSettings.cpp
Normal file
77
source/utils/WUPSBackendSettings.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "WUPSBackendSettings.h"
|
||||||
|
#include "fs/CFile.hpp"
|
||||||
|
#include "fs/FSUtils.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include "utils/utils.h"
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace WUPSBackendSettings {
|
||||||
|
namespace {
|
||||||
|
std::vector<std::string> sInactivePlugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define INACTIVE_PLUGINS_KEY "inactive_plugins"
|
||||||
|
|
||||||
|
bool LoadSettings() {
|
||||||
|
nlohmann::json j = nlohmann::json::object();
|
||||||
|
std::string folderPath = getModulePath() + "/configs/";
|
||||||
|
std::string filePath = folderPath + "wupsbackend.json";
|
||||||
|
|
||||||
|
if (!ParseJsonFromFile(filePath, j)) {
|
||||||
|
sInactivePlugins.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j.contains(INACTIVE_PLUGINS_KEY) && j[INACTIVE_PLUGINS_KEY].is_array()) {
|
||||||
|
for (auto &cur : j[INACTIVE_PLUGINS_KEY]) {
|
||||||
|
if (cur.is_string()) {
|
||||||
|
sInactivePlugins.push_back(cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SaveSettings() {
|
||||||
|
std::string folderPath = getModulePath() + "/configs/";
|
||||||
|
std::string filePath = folderPath + "wupsbackend.json";
|
||||||
|
if (!FSUtils::CreateSubfolder(folderPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFile file(filePath, CFile::WriteOnly);
|
||||||
|
if (!file.isOpen()) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Cannot create file %s", filePath.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json j = nlohmann::json::object();
|
||||||
|
j[INACTIVE_PLUGINS_KEY] = sInactivePlugins;
|
||||||
|
|
||||||
|
std::string jsonString = j.dump(4, ' ', false, nlohmann::json::error_handler_t::ignore);
|
||||||
|
auto writeResult = file.write((const uint8_t *) jsonString.c_str(), jsonString.size());
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
if (writeResult != (int32_t) jsonString.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetInactivePluginFilenames(std::span<std::string> filenames) {
|
||||||
|
sInactivePlugins.clear();
|
||||||
|
for (const auto &filename : filenames) {
|
||||||
|
sInactivePlugins.emplace_back(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string> &GetInactivePluginFilenames() {
|
||||||
|
return sInactivePlugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WUPSBackendSettings
|
15
source/utils/WUPSBackendSettings.h
Normal file
15
source/utils/WUPSBackendSettings.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace WUPSBackendSettings {
|
||||||
|
bool LoadSettings();
|
||||||
|
|
||||||
|
bool SaveSettings();
|
||||||
|
|
||||||
|
void SetInactivePluginFilenames(std::span<std::string> filenames);
|
||||||
|
|
||||||
|
const std::vector<std::string> &GetInactivePluginFilenames();
|
||||||
|
}; // namespace WUPSBackendSettings
|
@ -23,7 +23,8 @@ struct StoredBuffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum ConfigSubState {
|
enum ConfigSubState {
|
||||||
SUB_STATE_RUNNING = 0,
|
SUB_STATE_RUNNING = 0,
|
||||||
SUB_STATE_RETURN = 1,
|
SUB_STATE_RETURN = 1,
|
||||||
SUB_STATE_ERROR = 2,
|
SUB_STATE_RETURN_WITH_PLUGIN_RELOAD = 1,
|
||||||
|
SUB_STATE_ERROR = 2,
|
||||||
};
|
};
|
@ -90,18 +90,16 @@ ConfigSubState ConfigRenderer::UpdateStateMain(const Input &input) {
|
|||||||
mCursorPos--;
|
mCursorPos--;
|
||||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_PLUS) {
|
} else if (input.data.buttons_d & Input::eButtons::BUTTON_PLUS) {
|
||||||
if (mSetActivePluginsMode) {
|
if (mSetActivePluginsMode) {
|
||||||
if (mActivePluginsDirty) {
|
|
||||||
for (const auto &cur : mConfigs) {
|
|
||||||
gLoadOnNextLaunch.emplace_back(cur.getConfigInformation().pluginData, cur.isActivePlugin());
|
|
||||||
}
|
|
||||||
_SYSLaunchTitleWithStdArgsInNoSplash(OSGetTitleID(), nullptr);
|
|
||||||
}
|
|
||||||
mNeedRedraw = true;
|
mNeedRedraw = true;
|
||||||
mCategoryRenderer.reset();
|
mCategoryRenderer.reset();
|
||||||
return SUB_STATE_RETURN;
|
return SUB_STATE_RETURN_WITH_PLUGIN_RELOAD;
|
||||||
}
|
}
|
||||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_X) {
|
} else if (input.data.buttons_d & Input::eButtons::BUTTON_X) {
|
||||||
mSetActivePluginsMode = !mSetActivePluginsMode;
|
if (!mSetActivePluginsMode) {
|
||||||
|
mSetActivePluginsMode = true;
|
||||||
|
mNeedRedraw = true;
|
||||||
|
return SUB_STATE_RUNNING;
|
||||||
|
}
|
||||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_A) {
|
} else if (input.data.buttons_d & Input::eButtons::BUTTON_A) {
|
||||||
if (mSetActivePluginsMode) {
|
if (mSetActivePluginsMode) {
|
||||||
mActivePluginsDirty = true;
|
mActivePluginsDirty = true;
|
||||||
@ -123,7 +121,7 @@ ConfigSubState ConfigRenderer::UpdateStateMain(const Input &input) {
|
|||||||
for (auto &cur : mConfigs) {
|
for (auto &cur : mConfigs) {
|
||||||
cur.resetIsActivePlugin();
|
cur.resetIsActivePlugin();
|
||||||
}
|
}
|
||||||
mNeedRedraw = true;
|
mNeedRedraw = true;
|
||||||
mSetActivePluginsMode = false;
|
mSetActivePluginsMode = false;
|
||||||
return SUB_STATE_RUNNING;
|
return SUB_STATE_RUNNING;
|
||||||
} else {
|
} else {
|
||||||
@ -252,6 +250,18 @@ void ConfigRenderer::CallOnCloseCallback(const GeneralConfigInformation &info, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConfigRenderer::GetActivePluginsIfChanged(std::vector<PluginLoadWrapper> &result) {
|
||||||
|
if (mActivePluginsDirty) {
|
||||||
|
std::vector<std::string> inactive_plugins;
|
||||||
|
result.clear();
|
||||||
|
for (const auto &cur : mConfigs) {
|
||||||
|
result.emplace_back(cur.getConfigInformation().pluginData, cur.isActivePlugin());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigRenderer::CallOnCloseCallback(const GeneralConfigInformation &info, const WUPSConfigAPIBackend::WUPSConfig &config) {
|
void ConfigRenderer::CallOnCloseCallback(const GeneralConfigInformation &info, const WUPSConfigAPIBackend::WUPSConfig &config) {
|
||||||
CallOnCloseCallback(info, config.getCategories());
|
CallOnCloseCallback(info, config.getCategories());
|
||||||
for (const auto &item : config.getItems()) {
|
for (const auto &item : config.getItems()) {
|
||||||
|
@ -3,12 +3,13 @@
|
|||||||
#include "CategoryRenderer.h"
|
#include "CategoryRenderer.h"
|
||||||
#include "ConfigDefines.h"
|
#include "ConfigDefines.h"
|
||||||
#include "ConfigDisplayItem.h"
|
#include "ConfigDisplayItem.h"
|
||||||
|
#include "plugin/PluginLoadWrapper.h"
|
||||||
#include "utils/input/Input.h"
|
#include "utils/input/Input.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
|
||||||
#include <wups/config.h>
|
#include <wups/config.h>
|
||||||
|
|
||||||
class ConfigRenderer {
|
class ConfigRenderer {
|
||||||
@ -26,6 +27,8 @@ public:
|
|||||||
|
|
||||||
void ResetNeedsRedraw();
|
void ResetNeedsRedraw();
|
||||||
|
|
||||||
|
bool GetActivePluginsIfChanged(std::vector<PluginLoadWrapper> &result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConfigSubState UpdateStateMain(const Input &input);
|
ConfigSubState UpdateStateMain(const Input &input);
|
||||||
|
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
#include "ConfigRenderer.h"
|
#include "ConfigRenderer.h"
|
||||||
#include "config/WUPSConfigAPI.h"
|
#include "config/WUPSConfigAPI.h"
|
||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
|
#include "plugin/PluginLoadWrapper.h"
|
||||||
#include "utils/DrawUtils.h"
|
#include "utils/DrawUtils.h"
|
||||||
|
#include "utils/WUPSBackendSettings.h"
|
||||||
#include "utils/dc.h"
|
#include "utils/dc.h"
|
||||||
#include "utils/input/CombinedInput.h"
|
#include "utils/input/CombinedInput.h"
|
||||||
#include "utils/input/Input.h"
|
#include "utils/input/Input.h"
|
||||||
@ -13,9 +15,11 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <coreinit/title.h>
|
||||||
#include <globals.h>
|
#include <globals.h>
|
||||||
#include <memory/mappedmemory.h>
|
#include <memory/mappedmemory.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <sysapp/launch.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <wups/config.h>
|
#include <wups/config.h>
|
||||||
|
|
||||||
@ -214,16 +218,51 @@ void ConfigUtils::displayMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startTime = OSGetTime();
|
startTime = OSGetTime();
|
||||||
renderBasicScreen("Saving configs...");
|
|
||||||
|
|
||||||
for (const auto &plugin : gLoadedPlugins) {
|
DEBUG_FUNCTION_LINE_INFO(".");
|
||||||
const auto configData = plugin.getConfigData();
|
std::vector<PluginLoadWrapper> newActivePluginsList;
|
||||||
if (configData) {
|
|
||||||
if (configData->CallMenuClosedCallback() == WUPSCONFIG_API_RESULT_MISSING_CALLBACK) {
|
if (renderer.GetActivePluginsIfChanged(newActivePluginsList)) {
|
||||||
DEBUG_FUNCTION_LINE_WARN("CallMenuClosedCallback is missing for %s", plugin.getMetaInformation().getName().c_str());
|
startTime = OSGetTime();
|
||||||
|
renderBasicScreen("Applying changes, app will now restart...");
|
||||||
|
|
||||||
|
// Get list of inactive plugins to save them in the config
|
||||||
|
// Note: this does only consider plugin loaded from the sd card.
|
||||||
|
std::vector<std::string> newInactivePluginsList;
|
||||||
|
for (const auto &cur : newActivePluginsList) {
|
||||||
|
if (!cur.isLoadAndLink()) {
|
||||||
|
auto &source = cur.getPluginData()->getSource();
|
||||||
|
// TODO: Make sure to only use plugins from the actual plugin directory?
|
||||||
|
// atm nothing (to my knowledge) is using the WUPS API to load any plugin from a path though
|
||||||
|
if (source.ends_with(".wps")) {
|
||||||
|
std::size_t found = source.find_last_of("/\\");
|
||||||
|
std::string filename = source.substr(found + 1);
|
||||||
|
newInactivePluginsList.push_back(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gLoadOnNextLaunch = newActivePluginsList;
|
||||||
|
WUPSBackendSettings::SetInactivePluginFilenames(newInactivePluginsList);
|
||||||
|
WUPSBackendSettings::SaveSettings();
|
||||||
|
|
||||||
|
_SYSLaunchTitleWithStdArgsInNoSplash(OSGetTitleID(), nullptr);
|
||||||
|
// Make sure to wait at least 2 seconds so user can read the screen and
|
||||||
|
// are aware the app will restart now.
|
||||||
|
auto diffTime = OSTicksToMilliseconds(OSGetTime() - startTime);
|
||||||
|
if (diffTime < 2000) {
|
||||||
|
OSSleepTicks(OSTicksToMilliseconds(2000 - diffTime));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
renderBasicScreen("Saving configs...");
|
||||||
|
for (const auto &plugin : gLoadedPlugins) {
|
||||||
|
const auto configData = plugin.getConfigData();
|
||||||
|
if (configData) {
|
||||||
|
if (configData->CallMenuClosedCallback() == WUPSCONFIG_API_RESULT_MISSING_CALLBACK) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("CallMenuClosedCallback is missing for %s", plugin.getMetaInformation().getName().c_str());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CallHook(plugin, WUPS_LOADER_HOOK_CONFIG_CLOSED_DEPRECATED);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
CallHook(plugin, WUPS_LOADER_HOOK_CONFIG_CLOSED_DEPRECATED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,24 +174,10 @@ namespace StorageUtils {
|
|||||||
|
|
||||||
WUPSStorageError LoadFromFile(std::string_view plugin_id, nlohmann::json &outJson) {
|
WUPSStorageError LoadFromFile(std::string_view plugin_id, nlohmann::json &outJson) {
|
||||||
const std::string filePath = getPluginPath() + "/config/" + plugin_id.data() + ".json";
|
const std::string filePath = getPluginPath() + "/config/" + plugin_id.data() + ".json";
|
||||||
CFile file(filePath, CFile::ReadOnly);
|
if (ParseJsonFromFile(filePath, outJson)) {
|
||||||
if (!file.isOpen() || file.size() == 0) {
|
return WUPS_STORAGE_ERROR_SUCCESS;
|
||||||
return WUPS_STORAGE_ERROR_NOT_FOUND;
|
|
||||||
}
|
}
|
||||||
auto *json_data = static_cast<uint8_t *>(memalign(0x40, ROUNDUP(file.size() + 1, 0x40)));
|
return WUPS_STORAGE_ERROR_IO_ERROR;
|
||||||
if (!json_data) {
|
|
||||||
return WUPS_STORAGE_ERROR_MALLOC_FAILED;
|
|
||||||
}
|
|
||||||
WUPSStorageError result = WUPS_STORAGE_ERROR_SUCCESS;
|
|
||||||
if (const uint64_t readRes = file.read(json_data, file.size()); readRes == file.size()) {
|
|
||||||
json_data[file.size()] = '\0';
|
|
||||||
outJson = nlohmann::json::parse(json_data, nullptr, false);
|
|
||||||
} else {
|
|
||||||
result = WUPS_STORAGE_ERROR_IO_ERROR;
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
free(json_data);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WUPSStorageError LoadFromFile(std::string_view plugin_id, StorageItemRoot &rootItem) {
|
WUPSStorageError LoadFromFile(std::string_view plugin_id, StorageItemRoot &rootItem) {
|
||||||
|
@ -1,30 +1,54 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "fs/CFile.hpp"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
#include "json.hpp"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <coreinit/ios.h>
|
#include <coreinit/ios.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <wups/storage.h>
|
||||||
|
|
||||||
static std::string sPluginPath;
|
static std::string sPluginPath;
|
||||||
std::string getPluginPath() {
|
static std::string sModulePath;
|
||||||
if (!sPluginPath.empty()) {
|
static std::string sEnvironmentPath;
|
||||||
return sPluginPath;
|
|
||||||
|
std::string getEnvironmentPath() {
|
||||||
|
if (!sEnvironmentPath.empty()) {
|
||||||
|
return sEnvironmentPath;
|
||||||
}
|
}
|
||||||
char environmentPath[0x100] = {};
|
char environmentPath[0x100] = {};
|
||||||
|
|
||||||
if (const auto handle = IOS_Open("/dev/mcp", IOS_OPEN_READ); handle >= 0) {
|
if (const auto handle = IOS_Open("/dev/mcp", IOS_OPEN_READ); handle >= 0) {
|
||||||
int in = 0xF9; // IPC_CUSTOM_COPY_ENVIRONMENT_PATH
|
int in = 0xF9; // IPC_CUSTOM_COPY_ENVIRONMENT_PATH
|
||||||
if (IOS_Ioctl(handle, 100, &in, sizeof(in), environmentPath, sizeof(environmentPath)) != IOS_ERROR_OK) {
|
if (IOS_Ioctl(handle, 100, &in, sizeof(in), environmentPath, sizeof(environmentPath)) != IOS_ERROR_OK) {
|
||||||
return "fs:/vol/external01/wiiu/plugins";
|
return "fs:/vol/external01/wiiu/environments/aroma";
|
||||||
}
|
}
|
||||||
|
|
||||||
IOS_Close(handle);
|
IOS_Close(handle);
|
||||||
}
|
}
|
||||||
sPluginPath = std::string(environmentPath).append("/plugins");
|
sEnvironmentPath = environmentPath;
|
||||||
|
return sEnvironmentPath;
|
||||||
|
}
|
||||||
|
std::string getPluginPath() {
|
||||||
|
if (!sPluginPath.empty()) {
|
||||||
|
return sPluginPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
sPluginPath = getEnvironmentPath().append("/plugins");
|
||||||
return sPluginPath;
|
return sPluginPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getModulePath() {
|
||||||
|
if (!sModulePath.empty()) {
|
||||||
|
return sModulePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
sModulePath = getEnvironmentPath().append("/modules");
|
||||||
|
return sModulePath;
|
||||||
|
}
|
||||||
|
|
||||||
// https://gist.github.com/ccbrown/9722406
|
// https://gist.github.com/ccbrown/9722406
|
||||||
void dumpHex(const void *data, const size_t size) {
|
void dumpHex(const void *data, const size_t size) {
|
||||||
char ascii[17];
|
char ascii[17];
|
||||||
@ -86,4 +110,26 @@ void CustomDynLoadFree(void *addr) {
|
|||||||
if (const auto it = std::ranges::find(gAllocatedAddresses, addr); it != gAllocatedAddresses.end()) {
|
if (const auto it = std::ranges::find(gAllocatedAddresses, addr); it != gAllocatedAddresses.end()) {
|
||||||
gAllocatedAddresses.erase(it);
|
gAllocatedAddresses.erase(it);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseJsonFromFile(const std::string &filePath, nlohmann::json &outJson) {
|
||||||
|
CFile file(filePath, CFile::ReadOnly);
|
||||||
|
if (!file.isOpen() || file.size() == 0) {
|
||||||
|
return WUPS_STORAGE_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
auto *json_data = (uint8_t *) memalign(0x40, ROUNDUP(file.size() + 1, 0x40));
|
||||||
|
if (!json_data) {
|
||||||
|
return WUPS_STORAGE_ERROR_MALLOC_FAILED;
|
||||||
|
}
|
||||||
|
bool result = true;
|
||||||
|
uint64_t readRes = file.read(json_data, file.size());
|
||||||
|
if (readRes == file.size()) {
|
||||||
|
json_data[file.size()] = '\0';
|
||||||
|
outJson = nlohmann::json::parse(json_data, nullptr, false);
|
||||||
|
} else {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
free(json_data);
|
||||||
|
return result;
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "json.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <coreinit/dynload.h>
|
#include <coreinit/dynload.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -137,6 +138,10 @@ void append_move_all_values(Container &dest, Container &src) {
|
|||||||
|
|
||||||
std::string getPluginPath();
|
std::string getPluginPath();
|
||||||
|
|
||||||
|
std::string getModulePath();
|
||||||
|
|
||||||
OSDynLoad_Error CustomDynLoadAlloc(int32_t size, int32_t align, void **outAddr);
|
OSDynLoad_Error CustomDynLoadAlloc(int32_t size, int32_t align, void **outAddr);
|
||||||
|
|
||||||
void CustomDynLoadFree(void *addr);
|
void CustomDynLoadFree(void *addr);
|
||||||
|
|
||||||
|
bool ParseJsonFromFile(const std::string &filePath, nlohmann::json &outJson);
|
Loading…
x
Reference in New Issue
Block a user