Add support for the config and storage API. Bump version to 0.6

This commit is contained in:
Maschell
2021-04-07 00:23:23 +02:00
parent ed792716fe
commit 13ed348f43
34 changed files with 28162 additions and 98 deletions

View File

@@ -0,0 +1,679 @@
#include "ConfigUtils.h"
#include "logger.h"
#include "../config/WUPSConfig.h"
#include "../globals.h"
#include "DrawUtils.h"
#include "StringTools.h"
#include <string>
#include <vector>
#include <coreinit/screen.h>
#include <coreinit/cache.h>
#include <memory/mappedmemory.h>
#include <vpad/input.h>
#include <padscore/kpad.h>
#include <padscore/wpad.h>
#include <gx2/display.h>
#define COLOR_BACKGROUND Color(238, 238, 238, 255)
#define COLOR_TEXT Color(51, 51, 51, 255)
#define COLOR_TEXT2 Color(72, 72, 72, 255)
#define COLOR_DISABLED Color(255, 0, 0, 255)
#define COLOR_BORDER Color(204, 204, 204, 255)
#define COLOR_BORDER_HIGHLIGHTED Color(0x3478e4FF)
#define COLOR_WHITE Color(0xFFFFFFFF)
#define COLOR_BLACK Color(0, 0, 0, 255)
struct ConfigDisplayItem {
WUPSConfig* config;
std::string name;
std::string author;
std::string version;
bool enabled;
};
#define MAX_BUTTONS_ON_SCREEN 8
static uint32_t remapWiiMoteButtons(uint32_t buttons)
{
uint32_t conv_buttons = 0;
if(buttons & WPAD_BUTTON_LEFT)
conv_buttons |= VPAD_BUTTON_LEFT;
if(buttons & WPAD_BUTTON_RIGHT)
conv_buttons |= VPAD_BUTTON_RIGHT;
if(buttons & WPAD_BUTTON_DOWN)
conv_buttons |= VPAD_BUTTON_DOWN;
if(buttons & WPAD_BUTTON_UP)
conv_buttons |= VPAD_BUTTON_UP;
if(buttons & WPAD_BUTTON_PLUS)
conv_buttons |= VPAD_BUTTON_PLUS;
if(buttons & WPAD_BUTTON_B)
conv_buttons |= VPAD_BUTTON_B;
if(buttons & WPAD_BUTTON_A)
conv_buttons |= VPAD_BUTTON_A;
if(buttons & WPAD_BUTTON_MINUS)
conv_buttons |= VPAD_BUTTON_MINUS;
if(buttons & WPAD_BUTTON_HOME)
conv_buttons |= VPAD_BUTTON_HOME;
return conv_buttons;
}
static uint32_t remapClassicButtons(uint32_t buttons)
{
uint32_t conv_buttons = 0;
if(buttons & WPAD_CLASSIC_BUTTON_LEFT)
conv_buttons |= VPAD_BUTTON_LEFT;
if(buttons & WPAD_CLASSIC_BUTTON_RIGHT)
conv_buttons |= VPAD_BUTTON_RIGHT;
if(buttons & WPAD_CLASSIC_BUTTON_DOWN)
conv_buttons |= VPAD_BUTTON_DOWN;
if(buttons & WPAD_CLASSIC_BUTTON_UP)
conv_buttons |= VPAD_BUTTON_UP;
if(buttons & WPAD_CLASSIC_BUTTON_PLUS)
conv_buttons |= VPAD_BUTTON_PLUS;
if(buttons & WPAD_CLASSIC_BUTTON_X)
conv_buttons |= VPAD_BUTTON_X;
if(buttons & WPAD_CLASSIC_BUTTON_Y)
conv_buttons |= VPAD_BUTTON_Y;
if(buttons & WPAD_CLASSIC_BUTTON_B)
conv_buttons |= VPAD_BUTTON_B;
if(buttons & WPAD_CLASSIC_BUTTON_A)
conv_buttons |= VPAD_BUTTON_A;
if(buttons & WPAD_CLASSIC_BUTTON_MINUS)
conv_buttons |= VPAD_BUTTON_MINUS;
if(buttons & WPAD_CLASSIC_BUTTON_HOME)
conv_buttons |= VPAD_BUTTON_HOME;
if(buttons & WPAD_CLASSIC_BUTTON_ZR)
conv_buttons |= VPAD_BUTTON_ZR;
if(buttons & WPAD_CLASSIC_BUTTON_ZL)
conv_buttons |= VPAD_BUTTON_ZL;
if(buttons & WPAD_CLASSIC_BUTTON_R)
conv_buttons |= VPAD_BUTTON_R;
if(buttons & WPAD_CLASSIC_BUTTON_L)
conv_buttons |= VPAD_BUTTON_L;
return conv_buttons;
}
void ConfigUtils::displayMenu() {
std::vector<ConfigDisplayItem> configs;
for (int32_t plugin_index = 0; plugin_index < gPluginInformation->number_used_plugins; plugin_index++) {
plugin_information_single_t *plugin_data = &gPluginInformation->plugin_data[plugin_index];
if (plugin_data == nullptr) {
continue;
}
ConfigDisplayItem cfg;
cfg.name = std::string(plugin_data->meta.name);
cfg.author = std::string(plugin_data->meta.author);
cfg.version = std::string(plugin_data->meta.version);
cfg.enabled = true;
for (uint32_t j = 0; j < plugin_data->info.number_used_hooks; j++) {
replacement_data_hook_t *hook_data = &plugin_data->info.hooks[j];
if (hook_data->type == WUPS_LOADER_HOOK_GET_CONFIG/*WUPS_LOADER_HOOK_GET_CONFIG*/) {
if (hook_data->func_pointer == nullptr) {
break;
}
WUPSConfig *cur_config = reinterpret_cast<WUPSConfig *>(((WUPSConfigHandle (*)()) ((uint32_t *) hook_data->func_pointer))());
if(cur_config == nullptr){
break;
}
//if(cur_config > 0x8000000);
//DCFlushRange(&cur_config, sizeof(WUPSConfig*));
//DCFlushRange(cur_config, sizeof(WUPSConfig));
cfg.config = cur_config;
DEBUG_FUNCTION_LINE("name %s author %s version %s enabled %d config %08X",cfg.name.c_str(),cfg.author.c_str(),cfg.version.c_str(),cfg.enabled, cfg.config)
configs.push_back(cfg);
break;
}
}
}
ConfigDisplayItem* currentConfig = nullptr;
WUPSConfigCategory* currentCategory = nullptr;
uint32_t selectedBtn = 0;
uint32_t start = 0;
uint32_t end = MAX_BUTTONS_ON_SCREEN;
if (configs.size() < MAX_BUTTONS_ON_SCREEN) {
end = configs.size();
}
bool redraw = true;
uint32_t buttonsTriggered;
uint32_t buttonsReleased;
VPADStatus vpad_data{};
VPADReadError vpad_error;
KPADStatus kpad_data{};
int32_t kpad_error;
while (true) {
buttonsTriggered = 0;
buttonsReleased = 0;
VPADRead(VPAD_CHAN_0, &vpad_data, 1, &vpad_error);
if (vpad_error == VPAD_READ_SUCCESS) {
buttonsTriggered = vpad_data.trigger;
buttonsReleased = vpad_data.release;
}
for (int i = 0; i < 4; i++) {
if (KPADReadEx((KPADChan)i, &kpad_data, 1, &kpad_error) > 0) {
if (kpad_error == KPAD_ERROR_OK) {
if (kpad_data.extensionType == WPAD_EXT_CORE || kpad_data.extensionType == WPAD_EXT_NUNCHUK) {
buttonsTriggered |= remapWiiMoteButtons(kpad_data.trigger);
buttonsReleased |= remapWiiMoteButtons(kpad_data.release);
} else {
buttonsTriggered |= remapClassicButtons(kpad_data.classic.trigger);
buttonsReleased |= remapClassicButtons(kpad_data.classic.release);
}
}
}
}
if (buttonsTriggered & VPAD_BUTTON_HOME) {
break;
}
if (!currentConfig || !currentConfig->config) {
if (buttonsTriggered & VPAD_BUTTON_DOWN) {
if (selectedBtn < configs.size() - 1) {
selectedBtn++;
redraw = true;
}
}
else if (buttonsTriggered & VPAD_BUTTON_UP) {
if (selectedBtn > 0) {
selectedBtn--;
redraw = true;
}
}
if (buttonsTriggered & VPAD_BUTTON_X) {
configs[selectedBtn].enabled = !configs[selectedBtn].enabled;
redraw = true;
}
else if (buttonsTriggered & VPAD_BUTTON_A) {
currentConfig = &configs[selectedBtn];
if(currentConfig == nullptr){
DEBUG_FUNCTION_LINE("BYEBYE");
break;
}
selectedBtn = 0;
start = 0;
end = MAX_BUTTONS_ON_SCREEN;
auto cats = currentConfig->config->getCategories();
if (cats.size() < MAX_BUTTONS_ON_SCREEN) {
end = cats.size();
}
redraw = true;
continue;
}
if (selectedBtn >= end) {
end = selectedBtn + 1;
start = end - MAX_BUTTONS_ON_SCREEN;
}
else if (selectedBtn < start) {
start = selectedBtn;
end = start + MAX_BUTTONS_ON_SCREEN;
}
if (redraw) {
DrawUtils::beginDraw();
DrawUtils::clear(COLOR_BACKGROUND);
// draw buttons
uint32_t index = 8 + 24 + 8 + 4;
for (uint32_t i = start; i < end; i++) {
if (configs[i].enabled) {
DrawUtils::setFontColor(COLOR_TEXT);
} else {
DrawUtils::setFontColor(COLOR_DISABLED);
}
if (i == selectedBtn) {
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16*2, 44, 4, COLOR_BORDER_HIGHLIGHTED);
} else {
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16*2, 44, 2, configs[i].enabled ? COLOR_BORDER : COLOR_DISABLED);
}
DrawUtils::setFontSize(24);
DrawUtils::print(16*2, index + 8 + 24, configs[i].name.c_str());
uint32_t sz = DrawUtils::getTextWidth(configs[i].name.c_str());
DrawUtils::setFontSize(12);
DrawUtils::print(16*2 + sz + 4, index + 8 + 24, configs[i].author.c_str());
DrawUtils::print(SCREEN_WIDTH - 16*2, index + 8 + 24, configs[i].version.c_str(), true);
index += 42 + 8;
}
DrawUtils::setFontColor(COLOR_TEXT);
// draw top bar
DrawUtils::setFontSize(24);
DrawUtils::print(16, 6 + 24, "Wii U Plugin System Config Menu");
DrawUtils::setFontSize(18);
DrawUtils::print(SCREEN_WIDTH - 16, 8 + 24, "v1.0", true);
DrawUtils::drawRectFilled(8, 8 + 24 + 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK);
// draw bottom bar
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8*2, 3, COLOR_BLACK);
DrawUtils::setFontSize(18);
DrawUtils::print(16, SCREEN_HEIGHT - 8, "\ue07d Navigate ");
if (configs[selectedBtn].enabled) {
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 8, "\ue002 Disable / \ue000 Select", true);
} else {
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 8, "\ue002 Enable / \ue000 Select", true);
}
// draw scroll indicator
DrawUtils::setFontSize(24);
if (end < configs.size()) {
DrawUtils::print(SCREEN_WIDTH / 2 + 12, SCREEN_HEIGHT - 32, "\ufe3e", true);
}
if (start > 0) {
DrawUtils::print(SCREEN_WIDTH / 2 + 12, 32 + 20, "\ufe3d", true);
}
// draw home button
DrawUtils::setFontSize(18);
const char* exitHint = "\ue044 Exit";
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(exitHint) / 2, SCREEN_HEIGHT - 8, exitHint, true);
DrawUtils::endDraw();
redraw = false;
}
continue;
}
if(!currentCategory){
auto cats = currentConfig->config->getCategories();
if (buttonsTriggered & VPAD_BUTTON_DOWN) {
if (selectedBtn < cats.size() - 1) {
selectedBtn++;
redraw = true;
}
}
else if (buttonsTriggered & VPAD_BUTTON_UP) {
if (selectedBtn > 0) {
selectedBtn--;
redraw = true;
}
}
else if (buttonsTriggered & VPAD_BUTTON_A) {
currentCategory = cats[selectedBtn];
if(currentCategory == nullptr){
DEBUG_FUNCTION_LINE("BYEBYE");
break;
}
selectedBtn = 0;
start = 0;
end = MAX_BUTTONS_ON_SCREEN;
auto items = currentCategory->getItems();
if (items.size() < MAX_BUTTONS_ON_SCREEN) {
end = items.size();
}
redraw = true;
continue;
} else if (buttonsTriggered & VPAD_BUTTON_B) {
currentConfig = nullptr;
currentCategory = nullptr;
selectedBtn = 0;
start = 0;
end = MAX_BUTTONS_ON_SCREEN;
if (configs.size() < MAX_BUTTONS_ON_SCREEN) {
end = configs.size();
}
redraw = true;
continue;
}
if (selectedBtn >= end) {
end = selectedBtn + 1;
start = end - MAX_BUTTONS_ON_SCREEN;
}
else if (selectedBtn < start) {
start = selectedBtn;
end = start + MAX_BUTTONS_ON_SCREEN;
}
if (redraw) {
DrawUtils::beginDraw();
DrawUtils::clear(COLOR_BACKGROUND);
// draw buttons
uint32_t index = 8 + 24 + 8 + 4;
for (uint32_t i = start; i < end; i++) {
DrawUtils::setFontColor(COLOR_TEXT);
if (i == selectedBtn) {
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16*2, 44, 4, COLOR_BORDER_HIGHLIGHTED);
} else {
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16*2, 44, 2, COLOR_BORDER);
}
DrawUtils::setFontSize(24);
DrawUtils::print(16*2, index + 8 + 24, cats[i]->getName().c_str());
index += 42 + 8;
}
DrawUtils::setFontColor(COLOR_TEXT);
// draw top bar
DrawUtils::setFontSize(24);
DrawUtils::print(16, 6 + 24, currentConfig->config->getName().c_str());
DrawUtils::setFontSize(18);
DrawUtils::print(SCREEN_WIDTH - 16, 8 + 24, currentConfig->version.c_str(), true);
DrawUtils::drawRectFilled(8, 8 + 24 + 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK);
// draw bottom bar
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8*2, 3, COLOR_BLACK);
DrawUtils::setFontSize(18);
DrawUtils::print(16, SCREEN_HEIGHT - 8, "\ue07d Navigate ");
if (configs[selectedBtn].enabled) {
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 8, "\ue002 Disable / \ue000 Select", true);
} else {
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 8, "\ue002 Enable / \ue000 Select", true);
}
// draw scroll indicator
DrawUtils::setFontSize(24);
if (end < configs.size()) {
DrawUtils::print(SCREEN_WIDTH / 2 + 12, SCREEN_HEIGHT - 32, "\ufe3e", true);
}
if (start > 0) {
DrawUtils::print(SCREEN_WIDTH / 2 + 12, 32 + 20, "\ufe3d", true);
}
// draw home button
DrawUtils::setFontSize(18);
const char* exitHint = "\ue044 Exit";
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(exitHint) / 2, SCREEN_HEIGHT - 8, exitHint, true);
DrawUtils::endDraw();
redraw = false;
}
continue;
}
const std::vector<WUPSConfigItem *> config_items = currentCategory->getItems();
if (buttonsTriggered & VPAD_BUTTON_DOWN) {
if (selectedBtn < config_items.size() - 1) {
selectedBtn++;
redraw = true;
}
}
else if (buttonsTriggered & VPAD_BUTTON_UP) {
if (selectedBtn > 0) {
selectedBtn--;
redraw = true;
}
}
else if (buttonsTriggered & VPAD_BUTTON_B) {
currentCategory = nullptr;
selectedBtn = 0;
start = 0;
end = MAX_BUTTONS_ON_SCREEN;
auto catSize = currentConfig->config->getCategories().size();
if (catSize < MAX_BUTTONS_ON_SCREEN) {
end = catSize;
}
redraw = true;
continue;
}
WUPSConfigButtons pressedButtons = WUPS_CONFIG_BUTTON_NONE;
if (buttonsTriggered & VPAD_BUTTON_A) {
pressedButtons |= WUPS_CONFIG_BUTTON_A;
}
if (buttonsTriggered & VPAD_BUTTON_LEFT) {
pressedButtons |= WUPS_CONFIG_BUTTON_LEFT;
}
if (buttonsTriggered & VPAD_BUTTON_RIGHT) {
pressedButtons |= WUPS_CONFIG_BUTTON_RIGHT;
}
if (buttonsTriggered & VPAD_BUTTON_L) {
pressedButtons |= WUPS_CONFIG_BUTTON_L;
}
if (buttonsTriggered & VPAD_BUTTON_R) {
pressedButtons |= WUPS_CONFIG_BUTTON_R;
}
if (buttonsTriggered & VPAD_BUTTON_ZL) {
pressedButtons |= WUPS_CONFIG_BUTTON_ZL;
}
if (buttonsTriggered & VPAD_BUTTON_ZR) {
pressedButtons |= WUPS_CONFIG_BUTTON_ZR;
}
if (pressedButtons != WUPS_CONFIG_BUTTON_NONE) {
redraw = true;
}
if (selectedBtn >= end) {
end = selectedBtn + 1;
start = end - MAX_BUTTONS_ON_SCREEN;
}
else if (selectedBtn < start) {
start = selectedBtn;
end = start + MAX_BUTTONS_ON_SCREEN;
}
if (redraw) {
DrawUtils::beginDraw();
DrawUtils::clear(COLOR_BACKGROUND);
// draw buttons
uint32_t index = 8 + 24 + 8 + 4;
for (uint32_t i = start; i < end; i++) {
DrawUtils::setFontColor(COLOR_TEXT);
if (i == selectedBtn) {
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16*2, 44, 4, COLOR_BORDER_HIGHLIGHTED);
} else {
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16*2, 44, 2, COLOR_BORDER);
}
DrawUtils::setFontSize(24);
DrawUtils::print(16*2, index + 8 + 24, config_items[i]->getDisplayName().c_str());
if (i == selectedBtn) {
if (pressedButtons != WUPS_CONFIG_BUTTON_NONE) {
config_items[i]->onButtonPressed(pressedButtons);
}
DrawUtils::print(SCREEN_WIDTH - 16*2, index + 8 + 24, config_items[i]->getCurrentValueSelectedDisplay().c_str(), true);
}
else {
DrawUtils::print(SCREEN_WIDTH - 16*2, index + 8 + 24, config_items[i]->getCurrentValueDisplay().c_str(), true);
}
index += 42 + 8;
}
DrawUtils::setFontColor(COLOR_TEXT);
std::string headline;
StringTools::strprintf(headline, "%s - %s",currentConfig->config->getName().c_str(), currentCategory->getName().c_str());
// draw top bar
DrawUtils::setFontSize(24);
DrawUtils::print(16, 6 + 24, headline.c_str());
DrawUtils::drawRectFilled(8, 8 + 24 + 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK);
DrawUtils::setFontSize(18);
DrawUtils::print(SCREEN_WIDTH - 16, 8 + 24, currentConfig->version.c_str(), true);
// draw bottom bar
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8*2, 3, COLOR_BLACK);
DrawUtils::setFontSize(18);
DrawUtils::print(16, SCREEN_HEIGHT - 8, "\ue07d Navigate ");
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 8, "\ue001 Back", true);
// draw scroll indicator
DrawUtils::setFontSize(24);
if (end < configs.size()) {
DrawUtils::print(SCREEN_WIDTH / 2 + 12, SCREEN_HEIGHT - 32, "\ufe3e", true);
}
if (start > 0) {
DrawUtils::print(SCREEN_WIDTH / 2 + 12, 32 + 20, "\ufe3d", true);
}
// draw home button
DrawUtils::setFontSize(18);
const char* exitHint = "\ue044 Exit";
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(exitHint) / 2, SCREEN_HEIGHT - 8, exitHint, true);
DrawUtils::endDraw();
redraw = false;
}
}
for (const auto& element : configs) {
for (const auto& cat : element.config->getCategories()) {
for (const auto& item : cat->getItems()) {
if(item->isDirty()){
item->callCallback();
}
}
}
}
for (int32_t plugin_index = 0; plugin_index < gPluginInformation->number_used_plugins; plugin_index++) {
plugin_information_single_t *plugin_data = &gPluginInformation->plugin_data[plugin_index];
if (plugin_data == nullptr) {
continue;
}
for (uint32_t j = 0; j < plugin_data->info.number_used_hooks; j++) {
replacement_data_hook_t *hook_data = &plugin_data->info.hooks[j];
if (hook_data->type == WUPS_LOADER_HOOK_CONFIG_CLOSED) {
if (hook_data->func_pointer == nullptr) {
break;
}
((void (*)()) ((uint32_t *) hook_data->func_pointer))();
break;
}
}
}
for (const auto& element : configs) {
DEBUG_FUNCTION_LINE("Delete %08X", element.config);
delete element.config;
}
}
void ConfigUtils::openConfigMenu()
{
bool wasHomeButtonMenuEnabled = OSIsHomeButtonMenuEnabled();
OSScreenInit();
uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(SCREEN_TV);
uint32_t screen_buf1_size = OSScreenGetBufferSizeEx(SCREEN_DRC);
void* screenbuffer0 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf0_size, 0x100);
void* screenbuffer1 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf1_size, 0x100);
bool skipScreen0Free = false;
bool skipScreen1Free = false;
if (!screenbuffer0 || !screenbuffer1) {
if(screenbuffer0 == nullptr){
if(storedTVBuffer.buffer_size >= screen_buf0_size){
screenbuffer0 = storedTVBuffer.buffer;
skipScreen0Free = true;
DEBUG_FUNCTION_LINE("Use storedTVBuffer");
}
}
if(screenbuffer1 == nullptr){
if(storedDRCBuffer.buffer_size >= screen_buf1_size){
screenbuffer1 = storedDRCBuffer.buffer;
skipScreen1Free = true;
DEBUG_FUNCTION_LINE("Use storedDRCBuffer");
}
}
if (!screenbuffer0 || !screenbuffer1) {
DEBUG_FUNCTION_LINE("Failed to alloc buffers");
goto error_exit;
}
}
OSScreenSetBufferEx(SCREEN_TV, screenbuffer0);
OSScreenSetBufferEx(SCREEN_DRC, screenbuffer1);
OSScreenEnableEx(SCREEN_TV, 1);
OSScreenEnableEx(SCREEN_DRC, 1);
// Clear screens
OSScreenClearBufferEx(SCREEN_TV, 0);
OSScreenClearBufferEx(SCREEN_DRC, 0);
// Flip buffers
OSScreenFlipBuffersEx(SCREEN_TV);
OSScreenFlipBuffersEx(SCREEN_DRC);
DrawUtils::initBuffers(screenbuffer0, screen_buf0_size, screenbuffer1, screen_buf1_size);
DrawUtils::initFont();
// disable the home button menu to prevent opening it when exiting
OSEnableHomeButtonMenu(false);
displayMenu();
OSEnableHomeButtonMenu(wasHomeButtonMenuEnabled);
DrawUtils::deinitFont();
error_exit:
if(storedTVBuffer.buffer != nullptr) {
GX2SetTVBuffer(storedTVBuffer.buffer, storedTVBuffer.buffer_size, static_cast<GX2TVRenderMode>(storedTVBuffer.mode),
storedTVBuffer.surface_format, storedTVBuffer.buffering_mode);
}
if(storedDRCBuffer.buffer != nullptr) {
GX2SetDRCBuffer(storedDRCBuffer.buffer, storedDRCBuffer.buffer_size, static_cast<GX2DrcRenderMode>(storedDRCBuffer.mode),
storedDRCBuffer.surface_format, storedDRCBuffer.buffering_mode);
}
if (!skipScreen0Free && screenbuffer0) {
MEMFreeToMappedMemory(screenbuffer0);
screenbuffer0 = nullptr;
}
if (!skipScreen1Free && screenbuffer1) {
MEMFreeToMappedMemory(screenbuffer1);
screenbuffer1 = nullptr;
}
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include <gx2/enum.h>
struct StoredBuffer {
void* buffer;
uint32_t buffer_size;
uint32_t mode;
GX2SurfaceFormat surface_format;
GX2BufferingMode buffering_mode;
};
class ConfigUtils {
public:
static void openConfigMenu();
private:
static void displayMenu();
};

306
source/utils/DrawUtils.cpp Normal file
View File

@@ -0,0 +1,306 @@
#include "DrawUtils.h"
#include <coreinit/memory.h>
#include <coreinit/screen.h>
#include <png.h>
#include <ft2build.h>
#include FT_FREETYPE_H
// buffer width
#define TV_WIDTH 0x500
#define DRC_WIDTH 0x380
bool DrawUtils::isBackBuffer;
uint8_t *DrawUtils::tvBuffer = nullptr;
uint32_t DrawUtils::tvSize = 0;
uint8_t *DrawUtils::drcBuffer = nullptr;
uint32_t DrawUtils::drcSize = 0;
// Don't put those into the clase or we have to include ft everywhere
static FT_Library ft_lib = nullptr;
static FT_Face ft_face = nullptr;
static Color font_col(0xFFFFFFFF);
void DrawUtils::initBuffers(void *tvBuffer_, uint32_t tvSize_, void *drcBuffer_, uint32_t drcSize_) {
DrawUtils::tvBuffer = (uint8_t *) tvBuffer_;
DrawUtils::tvSize = tvSize_;
DrawUtils::drcBuffer = (uint8_t *) drcBuffer_;
DrawUtils::drcSize = drcSize_;
}
void DrawUtils::beginDraw() {
uint32_t pixel = *(uint32_t *) tvBuffer;
// check which buffer is currently used
OSScreenPutPixelEx(SCREEN_TV, 0, 0, 0xABCDEF90);
if (*(uint32_t *) tvBuffer == 0xABCDEF90) {
isBackBuffer = false;
} else {
isBackBuffer = true;
}
// restore the pixel we used for checking
*(uint32_t *) tvBuffer = pixel;
}
void DrawUtils::endDraw() {
// OSScreenFlipBuffersEx already flushes the cache?
// DCFlushRange(tvBuffer, tvSize);
// DCFlushRange(drcBuffer, drcSize);
OSScreenFlipBuffersEx(SCREEN_DRC);
OSScreenFlipBuffersEx(SCREEN_TV);
}
void DrawUtils::clear(Color col) {
OSScreenClearBufferEx(SCREEN_TV, col.color);
OSScreenClearBufferEx(SCREEN_DRC, col.color);
}
void DrawUtils::drawPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
float opacity = a / 255.0f;
// put pixel in the drc buffer
uint32_t i = (x + y * DRC_WIDTH) * 4;
if (i + 3 < drcSize / 2) {
if (isBackBuffer) {
i += drcSize / 2;
}
if (a == 0xFF) {
drcBuffer[i] = r;
drcBuffer[i + 1] = g;
drcBuffer[i + 2] = b;
} else {
drcBuffer[i] = r * opacity + drcBuffer[i] * (1 - opacity);
drcBuffer[i + 1] = g * opacity + drcBuffer[i + 1] * (1 - opacity);
drcBuffer[i + 2] = b * opacity + drcBuffer[i + 2] * (1 - opacity);
}
}
// scale and put pixel in the tv buffer
for (uint32_t yy = (y * 1.5); yy < ((y * 1.5) + 1); yy++) {
for (uint32_t xx = (x * 1.5); xx < ((x * 1.5) + 1); xx++) {
uint32_t i = (xx + yy * TV_WIDTH) * 4;
if (i + 3 < tvSize / 2) {
if (isBackBuffer) {
i += tvSize / 2;
}
if (a == 0xFF) {
tvBuffer[i] = r;
tvBuffer[i + 1] = g;
tvBuffer[i + 2] = b;
} else {
tvBuffer[i] = r * opacity + tvBuffer[i] * (1 - opacity);
tvBuffer[i + 1] = g * opacity + tvBuffer[i + 1] * (1 - opacity);
tvBuffer[i + 2] = b * opacity + tvBuffer[i + 2] * (1 - opacity);
}
}
}
}
}
void DrawUtils::drawRectFilled(uint32_t x, uint32_t y, uint32_t w, uint32_t h, Color col) {
for (uint32_t yy = y; yy < y + h; yy++) {
for (uint32_t xx = x; xx < x + w; xx++) {
drawPixel(xx, yy, col);
}
}
}
void DrawUtils::drawRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t borderSize, Color col) {
drawRectFilled(x, y, w, borderSize, col);
drawRectFilled(x, y + h - borderSize, w, borderSize, col);
drawRectFilled(x, y, borderSize, h, col);
drawRectFilled(x + w - borderSize, y, borderSize, h, col);
}
void DrawUtils::drawBitmap(uint32_t x, uint32_t y, uint32_t target_width, uint32_t target_height, const uint8_t *data) {
if (data[0] != 'B' || data[1] != 'M') {
// invalid header
return;
}
uint32_t dataPos = __builtin_bswap32(*(uint32_t *) &(data[0x0A]));
uint32_t width = __builtin_bswap32(*(uint32_t *) &(data[0x12]));
uint32_t height = __builtin_bswap32(*(uint32_t *) &(data[0x16]));
if (dataPos == 0) {
dataPos = 54;
}
data += dataPos;
// TODO flip image since bitmaps are stored upside down
for (uint32_t yy = y; yy < y + target_height; yy++) {
for (uint32_t xx = x; xx < x + target_width; xx++) {
uint32_t i = (((xx - x) * width / target_width) + ((yy - y) * height / target_height) * width) * 3;
drawPixel(xx, yy, data[i + 2], data[i + 1], data[i], 0xFF);
}
}
}
static void png_read_data(png_structp png_ptr, png_bytep outBytes, png_size_t byteCountToRead) {
void **data = (void **) png_get_io_ptr(png_ptr);
memcpy(outBytes, *data, byteCountToRead);
*((uint8_t **) data) += byteCountToRead;
}
void DrawUtils::drawPNG(uint32_t x, uint32_t y, const uint8_t *data) {
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (png_ptr == nullptr) {
return;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == nullptr) {
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
return;
}
png_set_read_fn(png_ptr, (void *) &data, png_read_data);
png_read_info(png_ptr, info_ptr);
uint32_t width = 0;
uint32_t height = 0;
int bitDepth = 0;
int colorType = -1;
uint32_t retval = png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colorType, nullptr, nullptr, nullptr);
if (retval != 1) {
return;
}
uint32_t bytesPerRow = png_get_rowbytes(png_ptr, info_ptr);
auto *rowData = new uint8_t[bytesPerRow];
for (uint32_t yy = y; yy < y + height; yy++) {
png_read_row(png_ptr, (png_bytep) rowData, nullptr);
for (uint32_t xx = x; xx < x + width; xx++) {
if (colorType == PNG_COLOR_TYPE_RGB_ALPHA) {
uint32_t i = (xx - x) * 4;
drawPixel(xx, yy, rowData[i], rowData[i + 1], rowData[i + 2], rowData[i + 3]);
} else if (colorType == PNG_COLOR_TYPE_RGB) {
uint32_t i = (xx - x) * 3;
drawPixel(xx, yy, rowData[i], rowData[i + 1], rowData[i + 2], 0xFF);
}
}
}
delete[] rowData;
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
}
void DrawUtils::initFont() {
void *font = nullptr;
uint32_t size = 0;
OSGetSharedData(OS_SHAREDDATATYPE_FONT_STANDARD, 0, &font, &size);
if (font && size) {
FT_Init_FreeType(&ft_lib);
FT_New_Memory_Face(ft_lib, (FT_Byte *) font, size, 0, &ft_face);
}
}
void DrawUtils::deinitFont() {
FT_Done_Face(ft_face);
FT_Done_FreeType(ft_lib);
}
void DrawUtils::setFontSize(uint32_t size) {
FT_Set_Pixel_Sizes(ft_face, 0, size);
}
void DrawUtils::setFontColor(Color col) {
font_col = col;
}
static void draw_freetype_bitmap(FT_Bitmap *bitmap, FT_Int x, FT_Int y) {
FT_Int i, j, p, q;
FT_Int x_max = x + bitmap->width;
FT_Int y_max = y + bitmap->rows;
for (i = x, p = 0; i < x_max; i++, p++) {
for (j = y, q = 0; j < y_max; j++, q++) {
if (i < 0 || j < 0 || i >= SCREEN_WIDTH || j >= SCREEN_HEIGHT) {
continue;
}
float opacity = bitmap->buffer[q * bitmap->pitch + p] / 255.0f;
DrawUtils::drawPixel(i, j, font_col.r, font_col.g, font_col.b, font_col.a * opacity);
}
}
}
void DrawUtils::print(uint32_t x, uint32_t y, const char *string, bool alignRight) {
auto *buffer = new wchar_t[strlen(string) + 1];
size_t num = mbstowcs(buffer, string, strlen(string));
if (num > 0) {
buffer[num] = 0;
} else {
wchar_t *tmp = buffer;
while ((*tmp++ = *string++));
}
print(x, y, buffer, alignRight);
delete[] buffer;
}
void DrawUtils::print(uint32_t x, uint32_t y, const wchar_t *string, bool alignRight) {
FT_GlyphSlot slot = ft_face->glyph;
FT_Vector pen = {(int) x, (int) y};
if (alignRight) {
pen.x -= getTextWidth(string);
}
for (; *string; string++) {
uint32_t charcode = *string;
if (charcode == '\n') {
pen.y += ft_face->size->metrics.height >> 6;
pen.x = x;
continue;
}
FT_Load_Glyph(ft_face, FT_Get_Char_Index(ft_face, charcode), FT_LOAD_DEFAULT);
FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
draw_freetype_bitmap(&slot->bitmap, pen.x + slot->bitmap_left, pen.y - slot->bitmap_top);
pen.x += slot->advance.x >> 6;
}
}
uint32_t DrawUtils::getTextWidth(const char *string) {
auto *buffer = new wchar_t[strlen(string) + 1];
size_t num = mbstowcs(buffer, string, strlen(string));
if (num > 0) {
buffer[num] = 0;
} else {
wchar_t *tmp = buffer;
while ((*tmp++ = *string++));
}
uint32_t width = getTextWidth(buffer);
delete[] buffer;
return width;
}
uint32_t DrawUtils::getTextWidth(const wchar_t *string) {
FT_GlyphSlot slot = ft_face->glyph;
uint32_t width = 0;
for (; *string; string++) {
FT_Load_Glyph(ft_face, FT_Get_Char_Index(ft_face, *string), FT_LOAD_BITMAP_METRICS_ONLY);
width += slot->advance.x >> 6;
}
return width;
}

57
source/utils/DrawUtils.h Normal file
View File

@@ -0,0 +1,57 @@
#pragma once
#include <cstdint>
// visible screen sizes
#define SCREEN_WIDTH 854
#define SCREEN_HEIGHT 480
union Color {
explicit Color(uint32_t color) {
this->color = color;
}
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
this->r = r; this->g = g; this->b = b; this->a = a;
}
uint32_t color{};
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};
};
class DrawUtils {
public:
static void initBuffers(void* tvBuffer, uint32_t tvSize, void* drcBuffer, uint32_t drcSize);
static void beginDraw();
static void endDraw();
static void clear(Color col);
static void drawPixel(uint32_t x, uint32_t y, Color col) { drawPixel(x, y, col.r, col.g, col.b, col.a); }
static void drawPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
static void drawRectFilled(uint32_t x, uint32_t y, uint32_t w, uint32_t h, Color col);
static void drawRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t borderSize, Color col);
static void drawBitmap(uint32_t x, uint32_t y, uint32_t target_width, uint32_t target_height, const uint8_t* data);
static void drawPNG(uint32_t x, uint32_t y, const uint8_t* data);
static void initFont();
static void deinitFont();
static void setFontSize(uint32_t size);
static void setFontColor(Color col);
static void print(uint32_t x, uint32_t y, const char* string, bool alignRight = false);
static void print(uint32_t x, uint32_t y, const wchar_t* string, bool alignRight = false);
static uint32_t getTextWidth(const char* string);
static uint32_t getTextWidth(const wchar_t* string);
private:
static bool isBackBuffer;
static uint8_t* tvBuffer;
static uint32_t tvSize;
static uint8_t* drcBuffer;
static uint32_t drcSize;
};

View File

@@ -0,0 +1,133 @@
#include "StorageUtils.h"
#include <string>
#include "utils/logger.h"
#include "utils/json.hpp"
#include "fs/CFile.hpp"
#include "fs/FSUtils.h"
static void processJson(wups_storage_item_t* items, nlohmann::json json) {
if (items == nullptr) {
return;
}
items->data = (wups_storage_item_t*) malloc(json.size() * sizeof(wups_storage_item_t));
items->data_size = json.size();
uint32_t index = 0;
for (auto it = json.begin(); it != json.end(); ++it) {
wups_storage_item_t* item = &((wups_storage_item_t*) items->data)[index];
item->type = WUPS_STORAGE_TYPE_INVALID;
item->pending_delete = false;
item->data = nullptr;
item->key = nullptr;
item->key = (char*) malloc(it.key().size() + 1);
strcpy(item->key, it.key().c_str());
if (it.value().is_string()) {
item->type = WUPS_STORAGE_TYPE_STRING;
uint32_t size = it.value().get<std::string>().size() + 1;
item->data = malloc(size);
item->data_size = size;
strcpy((char*) item->data, it.value().get<std::string>().c_str());
} else if (it.value().is_number_integer()) {
item->type = WUPS_STORAGE_TYPE_INT;
item->data = malloc(sizeof(int32_t));
item->data_size = sizeof(int32_t);
*(int32_t*) item->data = it.value().get<int32_t>();
} else if (it.value().is_object()) {
if (it.value().size() > 0) {
item->type = WUPS_STORAGE_TYPE_ITEM;
processJson(item, it.value());
}
} else {
DEBUG_FUNCTION_LINE("Unknown type %s for value %s", it.value().type_name(), it.key().c_str());
}
index++;
}
}
int StorageUtils::OpenStorage(const char* plugin_id, wups_storage_item_t* items) {
if (!plugin_id || !items) {
return WUPS_STORAGE_ERROR_INVALID_BACKEND_PARAMS;
}
std::string filePath = std::string("fs:/vol/external01/wiiu/plugins/config/") + plugin_id + ".json";
nlohmann::json j;
CFile file(filePath, CFile::ReadOnly);
if (file.isOpen() && file.size() > 0) {
uint8_t* json_data = new uint8_t[file.size() + 1];
json_data[file.size()] = '\0';
file.read(json_data, file.size());
file.close();
j = nlohmann::json::parse(json_data, nullptr, false);
delete[] json_data;
if (j == nlohmann::detail::value_t::discarded || j.empty() || !j.is_object()) {
return WUPS_STORAGE_ERROR_INVALID_JSON;
}
} else { // empty or no config exists yet
DEBUG_FUNCTION_LINE("open failed");
return WUPS_STORAGE_ERROR_SUCCESS;
}
processJson(items, j["storageitems"]);
return WUPS_STORAGE_ERROR_SUCCESS;
}
static nlohmann::json processItems(wups_storage_item_t* items) {
nlohmann::json json;
if (!items) {
return json;
}
for (uint32_t i = 0; i < items->data_size; i++) {
wups_storage_item_t* item = &((wups_storage_item_t*) items->data)[i];
if (item->pending_delete || item->type == WUPS_STORAGE_TYPE_INVALID || !item->data || !item->key) {
continue;
}
if (item->type == WUPS_STORAGE_TYPE_STRING) {
json[item->key] = (const char*) item->data;
} else if (item->type == WUPS_STORAGE_TYPE_INT) {
json[item->key] = *(int32_t*) item->data;
} else if (item->type == WUPS_STORAGE_TYPE_ITEM) {
json[item->key] = processItems(item);
} else {
DEBUG_FUNCTION_LINE("Saving type %d not implemented", item->type);
}
}
return json;
}
int StorageUtils::CloseStorage(const char* plugin_id, wups_storage_item_t* items) {
if (!plugin_id || !items) {
return WUPS_STORAGE_ERROR_INVALID_BACKEND_PARAMS;
}
std::string folderPath = "fs:/vol/external01/wiiu/plugins/config/";
std::string filePath = folderPath + plugin_id + ".json";
FSUtils::CreateSubfolder(folderPath.c_str());
CFile file(filePath, CFile::WriteOnly);
if (!file.isOpen()) {
DEBUG_FUNCTION_LINE("Cannot create file %s", filePath.c_str());
return WUPS_STORAGE_ERROR_IO;
};
nlohmann::json j;
j["storageitems"] = processItems(items);
std::string jsonString = j.dump(4);
file.write((const uint8_t*) jsonString.c_str(), jsonString.size());
file.close();
return WUPS_STORAGE_ERROR_SUCCESS;
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include <wups.h>
class StorageUtils {
public:
static int OpenStorage(const char* plugin_id, wups_storage_item_t* items);
static int CloseStorage(const char* plugin_id, wups_storage_item_t* items);
};

View File

@@ -16,10 +16,11 @@ void fillPluginInformation(plugin_information *out, PluginMetaInformation *metaI
strncpy(out->name, metaInformation->getName().c_str(), 255);
strncpy(out->license, metaInformation->getLicense().c_str(), 255);
strncpy(out->version, metaInformation->getVersion().c_str(), 255);
strncpy(out->id, metaInformation->getId().c_str(), 255);
out->size = metaInformation->getSize();
}
extern "C" int32_t WUPSLoadAndLinkByDataHandle(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size) {
extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size) {
gLinkOnReload.number_used_plugins = 0;
if (plugin_data_handle_list != nullptr && plugin_data_handle_list_size != 0) {
for (uint32_t i = 0; i < plugin_data_handle_list_size; i++) {
@@ -35,12 +36,12 @@ extern "C" int32_t WUPSLoadAndLinkByDataHandle(const plugin_data_handle *plugin_
}
DCFlushRange(&gLinkOnReload, sizeof(gLinkOnReload));
} else {
return ERROR_INVALID_ARG;
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
}
return ERROR_NONE;
return PLUGIN_BACKEND_API_ERROR_NONE;
}
extern "C" int32_t WUPSDeletePluginContainer(const plugin_container_handle *handle_list, uint32_t handle_list_size) {
extern "C" PluginBackendApiErrorType WUPSDeletePluginContainer(const plugin_container_handle *handle_list, uint32_t handle_list_size) {
if (handle_list != nullptr && handle_list_size != 0) {
for (uint32_t i = 0; i < handle_list_size; i++) {
auto handle = handle_list[i];
@@ -49,10 +50,10 @@ extern "C" int32_t WUPSDeletePluginContainer(const plugin_container_handle *hand
delete pluginContainer;
}
}
return ERROR_NONE;
return PLUGIN_BACKEND_API_ERROR_NONE;
}
extern "C" int32_t WUPSDeletePluginData(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size) {
extern "C" PluginBackendApiErrorType WUPSDeletePluginData(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size) {
if (plugin_data_handle_list != nullptr && plugin_data_handle_list_size != 0) {
for (uint32_t i = 0; i < plugin_data_handle_list_size; i++) {
auto handle = plugin_data_handle_list[i];
@@ -61,10 +62,10 @@ extern "C" int32_t WUPSDeletePluginData(const plugin_data_handle *plugin_data_ha
delete pluginData;
}
}
return ERROR_NONE;
return PLUGIN_BACKEND_API_ERROR_NONE;
}
extern "C" int32_t WUPSLoadPluginAsData(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_data_handle *out) {
extern "C" PluginBackendApiErrorType WUPSLoadPluginAsData(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_data_handle *out) {
std::optional<PluginData> pluginData;
if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != nullptr) {
pluginData = PluginDataFactory::load(path, gPluginDataHeap);
@@ -73,35 +74,35 @@ extern "C" int32_t WUPSLoadPluginAsData(GetPluginInformationInputType inputType,
memcpy(&data[0], buffer, size);
pluginData = PluginDataFactory::load(data, gPluginDataHeap);
} else {
return ERROR_INVALID_ARG;
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
}
if (!pluginData) {
DEBUG_FUNCTION_LINE("Failed to alloc plugin data");
return ERROR_FAILED_ALLOC;
return PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC;
}
if (out == nullptr) {
DEBUG_FUNCTION_LINE("out was NULL");
return ERROR_INVALID_ARG;
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
} else {
auto *pluginDataHandle = new PluginData(pluginData.value());
DEBUG_FUNCTION_LINE("Saving plugin data handle: %08X", pluginDataHandle);
*out = (uint32_t) pluginDataHandle;
}
return ERROR_NONE;
return PLUGIN_BACKEND_API_ERROR_NONE;
}
extern "C" int32_t WUPSLoadPluginAsDataByPath(plugin_data_handle *output, const char *path) {
extern "C" PluginBackendApiErrorType WUPSLoadPluginAsDataByPath(plugin_data_handle *output, const char *path) {
return WUPSLoadPluginAsData(PLUGIN_INFORMATION_INPUT_TYPE_PATH, path, nullptr, 0, output);
}
extern "C" int32_t WUPSLoadPluginAsDataByBuffer(plugin_data_handle *output, char *buffer, size_t size) {
extern "C" PluginBackendApiErrorType WUPSLoadPluginAsDataByBuffer(plugin_data_handle *output, char *buffer, size_t size) {
return WUPSLoadPluginAsData(PLUGIN_INFORMATION_INPUT_TYPE_BUFFER, nullptr, buffer, size, output);
}
extern "C" int32_t WUPSGetPluginMetaInformation(GetPluginInformationInputType inputType, const char* path, char *buffer, size_t size, plugin_information *output) {
extern "C" PluginBackendApiErrorType WUPSGetPluginMetaInformation(GetPluginInformationInputType inputType, const char* path, char *buffer, size_t size, plugin_information *output) {
std::optional<PluginMetaInformation> pluginInfo;
if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != nullptr) {
std::string pathStr(path);
@@ -111,34 +112,34 @@ extern "C" int32_t WUPSGetPluginMetaInformation(GetPluginInformationInputType in
DEBUG_FUNCTION_LINE("PLUGIN_INFORMATION_INPUT_TYPE_BUFFER %08X %d", buffer, size);
pluginInfo = PluginMetaInformationFactory::loadPlugin(buffer, size);
} else {
return ERROR_INVALID_ARG;
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
}
if (!pluginInfo) {
DEBUG_FUNCTION_LINE("Failed to load plugin meta information");
return ERROR_FILE_NOT_FOUND;
return PLUGIN_BACKEND_API_ERROR_FILE_NOT_FOUND;
}
DEBUG_FUNCTION_LINE("Loaded plugin meta information");
if (output == nullptr) {
return ERROR_INVALID_ARG;
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
} else {
fillPluginInformation(output, &pluginInfo.value());
}
return ERROR_NONE;
return PLUGIN_BACKEND_API_ERROR_NONE;
}
extern "C" int32_t WUPSGetPluginMetaInformationByPath(plugin_information *output, const char *path) {
extern "C" PluginBackendApiErrorType WUPSGetPluginMetaInformationByPath(plugin_information *output, const char *path) {
return WUPSGetPluginMetaInformation(PLUGIN_INFORMATION_INPUT_TYPE_PATH, path, nullptr, 0, output);
}
extern "C" int32_t WUPSGetPluginMetaInformationByBuffer(plugin_information *output, char *buffer, size_t size) {
extern "C" PluginBackendApiErrorType WUPSGetPluginMetaInformationByBuffer(plugin_information *output, char *buffer, size_t size) {
return WUPSGetPluginMetaInformation(PLUGIN_INFORMATION_INPUT_TYPE_BUFFER, nullptr, buffer, size, output);
}
extern "C" int32_t WUPSGetPluginDataForContainerHandles(const plugin_container_handle *plugin_container_handle_list, plugin_data_handle *plugin_data_list, uint32_t buffer_size) {
int res = ERROR_NONE;
extern "C" PluginBackendApiErrorType WUPSGetPluginDataForContainerHandles(const plugin_container_handle *plugin_container_handle_list, plugin_data_handle *plugin_data_list, uint32_t buffer_size) {
PluginBackendApiErrorType res = PLUGIN_BACKEND_API_ERROR_NONE;
if (plugin_container_handle_list != nullptr && buffer_size != 0) {
for (uint32_t i = 0; i < buffer_size; i++) {
auto handle = plugin_container_handle_list[i];
@@ -148,18 +149,19 @@ extern "C" int32_t WUPSGetPluginDataForContainerHandles(const plugin_container_h
plugin_data_list[i] = (uint32_t) pluginData;
}
} else {
res = ERROR_INVALID_ARG;
res = PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
}
return res;
}
extern "C" int32_t WUPSGetMetaInformation(const plugin_container_handle *plugin_container_handle_list, plugin_information *plugin_information_list, uint32_t buffer_size) {
int res = ERROR_NONE;
extern "C" PluginBackendApiErrorType WUPSGetMetaInformation(const plugin_container_handle *plugin_container_handle_list, plugin_information *plugin_information_list, uint32_t buffer_size) {
PluginBackendApiErrorType res = PLUGIN_BACKEND_API_ERROR_NONE;
if (plugin_container_handle_list != nullptr && buffer_size != 0) {
for (uint32_t i = 0; i < buffer_size; i++) {
auto handle = plugin_container_handle_list[i];
auto *container = (PluginContainer *) handle;
strncpy(plugin_information_list[i].id, container->metaInformation.getId().c_str(), 255);
strncpy(plugin_information_list[i].author, container->metaInformation.getAuthor().c_str(), 255);
strncpy(plugin_information_list[i].buildTimestamp, container->metaInformation.getBuildTimestamp().c_str(), 255);
strncpy(plugin_information_list[i].description, container->metaInformation.getDescription().c_str(), 255);
@@ -169,12 +171,12 @@ extern "C" int32_t WUPSGetMetaInformation(const plugin_container_handle *plugin_
plugin_information_list[i].size = container->metaInformation.getSize();
}
} else {
res = ERROR_INVALID_ARG;
res = PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
}
return res;
}
extern "C" int32_t WUPSGetLoadedPlugins(plugin_container_handle *io_handles, uint32_t buffer_size, uint32_t *outSize) {
extern "C" PluginBackendApiErrorType WUPSGetLoadedPlugins(plugin_container_handle *io_handles, uint32_t buffer_size, uint32_t *outSize) {
auto plugins = PluginContainerPersistence::loadPlugins(gPluginInformation);
uint32_t counter = 0;
for (auto &plugin: plugins) {
@@ -190,10 +192,9 @@ extern "C" int32_t WUPSGetLoadedPlugins(plugin_container_handle *io_handles, uin
if (outSize != nullptr) {
*outSize = counter;
}
return 0;
return PLUGIN_BACKEND_API_ERROR_NONE;
}
WUMS_EXPORT_FUNCTION(WUPSLoadPluginAsDataByPath);
WUMS_EXPORT_FUNCTION(WUPSLoadPluginAsDataByBuffer);
WUMS_EXPORT_FUNCTION(WUPSLoadPluginAsData);

View File

@@ -1,61 +1,37 @@
#pragma once
#include <wums.h>
#include <wups_backend/import_defines.h>
#ifdef __cplusplus
extern "C" {
#endif
#define ERROR_NONE 0
#define ERROR_INVALID_SIZE 0xFFFFFFFF
#define ERROR_INVALID_ARG 0xFFFFFFFE
#define ERROR_FAILED_ALLOC 0xFFFFFFFD
#define ERROR_FILE_NOT_FOUND 0xFFFFFFFC
typedef enum GetPluginInformationInputType {
PLUGIN_INFORMATION_INPUT_TYPE_PATH = 0,
PLUGIN_INFORMATION_INPUT_TYPE_BUFFER = 1,
} GetPluginInformationInputType;
typedef uint32_t plugin_container_handle;
typedef uint32_t plugin_data_handle;
/* plugin_information message */
typedef struct __attribute__((__packed__)) plugin_information {
char name[256];
char author[256];
char buildTimestamp[256];
char description[256];
char license[256];
char version[256];
size_t size;
} plugin_information;
void fillPluginInformation(plugin_information *out, PluginMetaInformation *metaInformation);
int32_t WUPSLoadAndLinkByDataHandle(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size);
PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size);
int32_t WUPSDeletePluginContainer(const plugin_container_handle *handle_list, uint32_t handle_list_size);
PluginBackendApiErrorType WUPSDeletePluginContainer(const plugin_container_handle *handle_list, uint32_t handle_list_size);
int32_t WUPSDeletePluginData(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size);
PluginBackendApiErrorType WUPSDeletePluginData(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size);
int32_t WUPSLoadPluginAsData(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_data_handle *out);
PluginBackendApiErrorType WUPSLoadPluginAsData(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_data_handle *out);
int32_t WUPSLoadPluginAsDataByPath(plugin_data_handle *output, const char *path);
PluginBackendApiErrorType WUPSLoadPluginAsDataByPath(plugin_data_handle *output, const char *path);
int32_t WUPSLoadPluginAsDataByBuffer(plugin_data_handle *output, char *buffer, size_t size);
PluginBackendApiErrorType WUPSLoadPluginAsDataByBuffer(plugin_data_handle *output, char *buffer, size_t size);
int32_t WUPSGetPluginMetaInformation(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_information *output);
PluginBackendApiErrorType WUPSGetPluginMetaInformation(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_information *output);
int32_t WUPSGetPluginMetaInformationByPath(plugin_information *output, const char *path);
PluginBackendApiErrorType WUPSGetPluginMetaInformationByPath(plugin_information *output, const char *path);
int32_t WUPSGetPluginMetaInformationByBuffer(plugin_information *output, char *buffer, size_t size);
PluginBackendApiErrorType WUPSGetPluginMetaInformationByBuffer(plugin_information *output, char *buffer, size_t size);
int32_t WUPSGetPluginDataForContainerHandles(const plugin_container_handle *plugin_container_handle_list, plugin_data_handle *plugin_data_list, uint32_t buffer_size);
PluginBackendApiErrorType WUPSGetPluginDataForContainerHandles(const plugin_container_handle *plugin_container_handle_list, plugin_data_handle *plugin_data_list, uint32_t buffer_size);
int32_t WUPSGetMetaInformation(const plugin_container_handle *plugin_container_handle_list, plugin_information *plugin_information_list, uint32_t buffer_size);
PluginBackendApiErrorType WUPSGetMetaInformation(const plugin_container_handle *plugin_container_handle_list, plugin_information *plugin_information_list, uint32_t buffer_size);
int32_t WUPSGetLoadedPlugins(plugin_container_handle *io_handles, uint32_t buffer_size, uint32_t *outSize);
PluginBackendApiErrorType WUPSGetLoadedPlugins(plugin_container_handle *io_handles, uint32_t buffer_size, uint32_t *outSize);
#ifdef __cplusplus
}

25447
source/utils/json.hpp Normal file

File diff suppressed because it is too large Load Diff