From c3cca4926c5c22fbe64a451c6465a809bf878ff7 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 17 May 2020 21:08:13 +0200 Subject: [PATCH] Build with WiiUModuleSystem, export a bunch of useful functions to control the backend --- .gitignore | 1 + Makefile | 14 +-- source/crt0.s | 29 ------ source/main.cpp | 3 + source/utils/exports.cpp | 207 +++++++++++++++++++++++++++++++++++++++ source/utils/exports.h | 62 ++++++++++++ 6 files changed, 281 insertions(+), 35 deletions(-) delete mode 100644 source/crt0.s create mode 100644 source/utils/exports.cpp create mode 100644 source/utils/exports.h diff --git a/.gitignore b/.gitignore index 06980ab..ba57c28 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ build/ .idea/ cmake-build-debug/ CMakeLists.txt +*.wms diff --git a/Makefile b/Makefile index 664b7f4..4f60336 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,11 @@ endif TOPDIR ?= $(CURDIR) -include $(DEVKITPRO)/wut/share/wut_rules +include $(DEVKITPRO)/wums/share/wums_rules WUPS_ROOT := $(DEVKITPRO)/wups +WUMS_ROOT := $(DEVKITPRO)/wums +WUT_ROOT := $(DEVKITPRO)/wut #------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -40,15 +42,15 @@ CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ CXXFLAGS := $(CFLAGS) -std=c++17 ASFLAGS := -g $(ARCH) -LDFLAGS = -g $(ARCH) $(RPXSPECS) --entry=_start -Wl,-Map,$(notdir $*.map) +LDFLAGS = -g $(ARCH) $(WUMSSPECS) -Wl,-Map,$(notdir $*.map) -LIBS := -lwut -lwups +LIBS := -lwums -lwut -lwups #------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level # containing include and lib #------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUPS_ROOT) +LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUPS_ROOT) $(WUMS_ROOT) #------------------------------------------------------------------------------- @@ -119,9 +121,9 @@ DEPENDS := $(OFILES:.o=.d) #------------------------------------------------------------------------------- # main targets #------------------------------------------------------------------------------- -all : $(OUTPUT).rpx +all : $(OUTPUT).wms -$(OUTPUT).rpx : $(OUTPUT).elf +$(OUTPUT).wms : $(OUTPUT).elf $(OUTPUT).elf : $(OFILES) $(OFILES_SRC) : $(HFILES_BIN) diff --git a/source/crt0.s b/source/crt0.s deleted file mode 100644 index 595a028..0000000 --- a/source/crt0.s +++ /dev/null @@ -1,29 +0,0 @@ -.extern main -.extern exit -.extern __init_wut -.extern __fini_wut - -.global _start -_start: - stwu 1, -0x28(1) - mflr 0 - stw 0, 0x2C(1) - stw 31, 0x24(1) - or 31, 1, 1 - stw 3, 0x18(31) - stw 4, 0x1C(31) - bl __init_wut - lwz 4, 0x1C(31) - lwz 3, 0x18(31) - bl main - or 9, 3, 3 - stw 9, 0x8(31) - bl __fini_wut - lwz 9, 0x8(31) - or 3, 9, 9 - addi 11, 31, 0x28 - lwz 0, 0x4(11) - mtlr 0 - lwz 31, -0x4(11) - or 1, 11, 11 - blr \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index fc2a2fa..7f92d22 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -25,8 +25,11 @@ #include "PluginManagement.h" #include "globals.h" #include +#include +#include #include +WUMS_MODULE_EXPORT_NAME("homebrew_wupsbackend"); int test(); diff --git a/source/utils/exports.cpp b/source/utils/exports.cpp new file mode 100644 index 0000000..50f41c3 --- /dev/null +++ b/source/utils/exports.cpp @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "exports.h" +#include + +void fillPluginInformation(plugin_information *out, PluginMetaInformation *metaInformation) { + strncpy(out->author, metaInformation->getAuthor().c_str(), 255); + strncpy(out->buildTimestamp, metaInformation->getBuildTimestamp().c_str(), 255); + strncpy(out->description, metaInformation->getDescription().c_str(), 255); + strncpy(out->name, metaInformation->getName().c_str(), 255); + strncpy(out->license, metaInformation->getLicense().c_str(), 255); + strncpy(out->version, metaInformation->getVersion().c_str(), 255); + out->size = metaInformation->getSize(); +} + +int32_t 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 != NULL && 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]; + PluginData *pluginData = (PluginData *) handle; + DEBUG_FUNCTION_LINE("Saving plugin data %08X", pluginData); + PluginDataPersistence::save(&gLinkOnReload.plugin_data[gLinkOnReload.number_used_plugins], *pluginData); + + gLinkOnReload.number_used_plugins++; + } + if (gLinkOnReload.number_used_plugins > 0) { + gLinkOnReload.loadOnReload = true; + } + DCFlushRange(&gLinkOnReload, sizeof(gLinkOnReload)); + } else { + return ERROR_INVALID_ARG; + } + return ERROR_NONE; +} + +int32_t WUPSDeletePluginContainer(const plugin_container_handle *handle_list, uint32_t handle_list_size) { + if (handle_list != NULL && handle_list_size != 0) { + for (uint32_t i = 0; i < handle_list_size; i++) { + auto handle = handle_list[i]; + PluginContainer *pluginContainer = (PluginContainer *) handle; + DEBUG_FUNCTION_LINE("Delete plugin container: %08X", pluginContainer); + delete pluginContainer; + } + } + return ERROR_NONE; +} + +int32_t WUPSDeletePluginData(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size) { + if (plugin_data_handle_list != NULL && 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]; + PluginData *pluginData = (PluginData *) handle; + DEBUG_FUNCTION_LINE("delete plugin data %08X", pluginData); + delete pluginData; + } + } + return ERROR_NONE; +} + +int32_t WUPSLoadPluginAsData(GetPluginInformationInputType inputType, const char* path, char* buffer, size_t size, plugin_data_handle * out) { + std::optional pluginData; + if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH) { + pluginData = PluginDataFactory::load(path, pluginDataHeap); + } else if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_BUFFER) { + std::vector data(size); + memcpy(&data[0], buffer, size); + pluginData = PluginDataFactory::load(data, pluginDataHeap); + } else { + return ERROR_INVALID_ARG; + } + + if (!pluginData) { + DEBUG_FUNCTION_LINE("Failed to alloc plugin data"); + return ERROR_FAILED_ALLOC; + } + + if (out == NULL) { + DEBUG_FUNCTION_LINE("out was NULL"); + return ERROR_INVALID_ARG; + } else { + PluginData *pluginDataHeap = new PluginData(pluginData.value()); + DEBUG_FUNCTION_LINE("Saving handle %08X", pluginDataHeap); + *out = (uint32_t) pluginDataHeap; + } + + return ERROR_NONE; +} + +int32_t WUPSLoadPluginAsDataByPath(plugin_data_handle * output, const char* path){ + return WUPSLoadPluginAsData(PLUGIN_INFORMATION_INPUT_TYPE_PATH, path, NULL, 0, output); +} + +int32_t WUPSLoadPluginAsDataByBuffer(plugin_data_handle * output, char* buffer, size_t size){ + return WUPSLoadPluginAsData(PLUGIN_INFORMATION_INPUT_TYPE_BUFFER, NULL, buffer, size, output); +} + +int32_t WUPSGetPluginMetaInformation(GetPluginInformationInputType inputType, const char* path, char* buffer, size_t size, plugin_information * output) { + std::optional pluginInfo; + if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != NULL) { + DEBUG_FUNCTION_LINE("PLUGIN_INFORMATION_INPUT_TYPE_PATH %s", path); + pluginInfo = PluginMetaInformationFactory::loadPlugin(path); + } else if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_BUFFER && buffer != NULL && size > 0) { + DEBUG_FUNCTION_LINE("PLUGIN_INFORMATION_INPUT_TYPE_BUFFER %08X %d", buffer, size); + pluginInfo = PluginMetaInformationFactory::loadPlugin(buffer, size); + } else { + return ERROR_INVALID_ARG; + } + + if (!pluginInfo) { + DEBUG_FUNCTION_LINE("Failed to load plugin"); + return ERROR_FILE_NOT_FOUND; + } + + DEBUG_FUNCTION_LINE("loaded plugin"); + + if (output == NULL) { + return ERROR_INVALID_ARG; + } else { + fillPluginInformation(output, &pluginInfo.value()); + } + return ERROR_NONE; +} + +int32_t WUPSGetPluginMetaInformationByPath(plugin_information * output, const char* path) { + return WUPSGetPluginMetaInformation(PLUGIN_INFORMATION_INPUT_TYPE_PATH, path, NULL, 0, output); +} + +int32_t WUPSGetPluginMetaInformationByBuffer(plugin_information * output, char* buffer, size_t size) { + return WUPSGetPluginMetaInformation(PLUGIN_INFORMATION_INPUT_TYPE_BUFFER, NULL, buffer, size, output); +} + +int32_t WUPSGetPluginDataForContainerHandles(const plugin_container_handle *plugin_container_handle_list, plugin_data_handle *plugin_data_list , uint32_t buffer_size) { + int res; + if (plugin_container_handle_list != NULL && buffer_size != 0) { + for (uint32_t i = 0; i < buffer_size; i++) { + auto handle = plugin_container_handle_list[i]; + PluginContainer *container = (PluginContainer *) handle; + PluginData *pluginData = new PluginData(container->getPluginData()); + DEBUG_FUNCTION_LINE("Created pluginData [%08X]", pluginData); + plugin_data_list[i] = (uint32_t) pluginData; + } + } else { + res = ERROR_INVALID_ARG; + } + return res; +} + +int32_t WUPSGetMetaInformation(plugin_container_handle * plugin_container_handle_list, plugin_information * plugin_information_list, uint32_t buffer_size) { + int res = ERROR_NONE; + if (plugin_container_handle_list != NULL && buffer_size != 0) { + for (uint32_t i = 0; i < buffer_size; i++) { + auto handle = plugin_container_handle_list[i]; + PluginContainer *container = (PluginContainer *) handle; + + 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); + strncpy(plugin_information_list[i].name, container->metaInformation.getName().c_str(), 255); + strncpy(plugin_information_list[i].license, container->metaInformation.getLicense().c_str(), 255); + strncpy(plugin_information_list[i].version, container->metaInformation.getVersion().c_str(), 255); + plugin_information_list[i].size = container->metaInformation.getSize(); + } + } else { + res = ERROR_INVALID_ARG; + } + return res; +} + +int32_t 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) { + if (counter < buffer_size) { + PluginContainer *container = new PluginContainer(plugin); + DEBUG_FUNCTION_LINE("Created container [%08X]", container); + io_handles[counter] = (uint32_t) container; + counter++; + } else { + break; + } + } + if(*outSize){ + *outSize = counter; + } + return 0; +} + + +WUMS_EXPORT_FUNCTION(WUPSLoadPluginAsDataByPath); +WUMS_EXPORT_FUNCTION(WUPSLoadPluginAsDataByBuffer); +WUMS_EXPORT_FUNCTION(WUPSLoadPluginAsData); +WUMS_EXPORT_FUNCTION(WUPSLoadAndLinkByDataHandle); +WUMS_EXPORT_FUNCTION(WUPSDeletePluginContainer); +WUMS_EXPORT_FUNCTION(WUPSDeletePluginData); +WUMS_EXPORT_FUNCTION(WUPSGetPluginMetaInformation); +WUMS_EXPORT_FUNCTION(WUPSGetPluginMetaInformationByPath); +WUMS_EXPORT_FUNCTION(WUPSGetPluginMetaInformationByBuffer); +WUMS_EXPORT_FUNCTION(WUPSGetMetaInformation); +WUMS_EXPORT_FUNCTION(WUPSGetLoadedPlugins); +WUMS_EXPORT_FUNCTION(WUPSGetPluginDataForContainerHandles); diff --git a/source/utils/exports.h b/source/utils/exports.h new file mode 100644 index 0000000..6c72f85 --- /dev/null +++ b/source/utils/exports.h @@ -0,0 +1,62 @@ +#pragma once + +#include + +#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); + +int32_t 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); + +int32_t 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); + +int32_t 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); + +int32_t WUPSGetPluginMetaInformationByPath(plugin_information *output, const char *path); + +int32_t 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); + +int32_t WUPSGetMetaInformation(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); + +#ifdef __cplusplus +} +#endif \ No newline at end of file