diff --git a/.gitignore b/.gitignore index c6f6170..9e3fcad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ loader/build/* loader/WiiUPluginLoader.cbp loader/*.elf +example_plugin/bin/* +example_plugin/build/* +example_plugin_pic/* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1b2f34c --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPRO") +endif + +WUPSDIR := $(DEVKITPRO)/wups + +# Rule to install wups. +PHONY += install +install : wups.ld wups_elf.ld + $(addprefix $Qrm -rf ,$(wildcard $(WUPSDIR))) + $Qmkdir $(WUPSDIR) + $Qcp -r wups_include $(WUPSDIR)/include + $Qcp -r wups.ld $(WUPSDIR) + $Qcp -r wups_elf.ld $(WUPSDIR) + + # Rule to install wups. +PHONY += uninstall +uninstall : + $(addprefix $Qrm -rf ,$(wildcard $(WUPSDIR))) \ No newline at end of file diff --git a/README.MD b/README.MD index 543d4b5..398c65c 100644 --- a/README.MD +++ b/README.MD @@ -131,3 +131,6 @@ Platform: IOS Notes: TODO https://github.com/comex/substitute +# Credits +Some files are based on brainslug by Chadderz: +https://github.com/Chadderz121/brainslug-wii diff --git a/example_plugin/Makefile b/example_plugin/Makefile new file mode 100644 index 0000000..01f4023 --- /dev/null +++ b/example_plugin/Makefile @@ -0,0 +1,177 @@ +############################################################################### +# Makefile +# by Alex Chadwick +# +# A makefile script for generation of a brainslug module +############################################################################### +# Hopefully you shouldn't need to change anything in this file. +# Alter makefile.mk to change common settings. + +############################################################################### +# devkitpro settings +ifeq ($(strip $(DEVKITPRO)),) + $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPro") +endif +ifeq ($(strip $(DEVKITPPC)),) + $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +WUPSDIR := $(DEVKITPRO)/wups +GCC_VER := $(shell $(DEVKITPPC)/bin/powerpc-eabi-gcc -dumpversion) + +PATH := $(DEVKITPPC)/bin:$(PATH) +LIB_INC_DIRS := $(DEVKITPPC)/lib/gcc/powerpc-eabi/$(GCC_VER)/include \ + $(DEVKITPPC)/lib/gcc/powerpc-eabi/$(GCC_VER)/include-fixed \ + $(DEVKITPPC)/lib/gcc/powerpc-eabi/$(GCC_VER)/include-fixed \ + $(DEVKITPPC)/powerpc-eabi/include \ + $(WUPSDIR)/include + +include makefile.mk + +LIB_DIRS += $(DEVKITPPC)/lib\gcc\powerpc-eabi\6.3.0 +LIBS += gcc +############################################################################### +# Parameters + +# A comma to make writing commands easier +C := , +# Used to suppress command echo. +Q ?= @ +LOG ?= @echo $@ +# The intermediate directory for compiled object files. +BUILD ?= build +# The name of the assembler listing file to generate. +LIST ?= $(TARGET:.mod=.list) +# The name of the map file to generate. +MAP ?= $(TARGET:.mod=.map) + +INC_DIRS += $(LIB_INC_DIRS) + +############################################################################### +# Compiler settings + +# The toolchain to use. +PREFIX ?= powerpc-eabi- +# Tools to use +AS := $(PREFIX)as +LD := $(PREFIX)ld +CC := $(PREFIX)g++ +OBJDUMP := $(PREFIX)objdump + +# --relocatable: make sure ld doesn't remove relocations wups will need +# -s: strip local symbols to speed linking +# --gc-sections: remove unneeded symbols +# -T: use the linker script specified (to force certain wups sections together) +# -Map: generate a map file +LDFLAGS += --relocatable -s -u wups_load -u wups_meta \ + -T $(WUPSDIR)/wups.ld \ + $(patsubst %,-Map %,$(strip $(MAP))) +LD1FLAGS += --relocatable -s \ + -T $(WUPSDIR)/wups_elf.ld + +# -O2: optimise lots +# -Wall: generate lots of warnings +# -x c: compile as C code +# -std=gnu11: use the C11 standard with GNU extensions +# -nostdinc: don't include standard headers (we don't have all the symbols) +# -ffreestanding: we don't have libc; don't expect we do +# -DGEKKO: define the symbol GEKKO (used in some libogc headers) +# -DHW_RVL: define the symbol HW_RVL (used in some libogc headers) +# -D__wii__: define the symbol __wii__ (used in some libogc headers) +# -mrvl: enable wii/gamecube compilation +# -mcpu=750: enable processor specific compilation +# -meabi: enable eabi specific compilation +# -mhard-float: enable hardware floating point instructions +# -fshort-wchar: use 16 bit whcar_t type in keeping with Wii executables +# -fno-common: stop common variables which the loader can't understand +# -msdata-none: do not use r2 or r13 as small data areas +# -memb: enable embedded application specific compilation +# -ffunction-sections: split up functions so linker can garbage collect +# -fdata-sections: split up data so linker can garbage collect +CFLAGS += -O0 -Wall -x c -std=gnu11 \ + -nostdinc -ffreestanding \ + -DGEKKO_U -D__wiiu__ \ + -mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar -fno-common \ + -msdata=none -memb -ffunction-sections -fdata-sections + +ifdef DEBUG +else + CFLAGS += -DNDEBUG +endif + +############################################################################### +# Variable init + +# Phony targets +PHONY := + +############################################################################### +# Rule to make everything. +PHONY += all + +all : $(TARGET) + +############################################################################### +# Derived rules + +LDFLAGS += $(patsubst %,-l %,$(LIBS)) $(patsubst %,-l %,$(LIBS)) \ + $(patsubst %,-L %,$(LIB_DIRS)) $(patsubst %,-L %/lib,$(LIB_DIRS)) +CFLAGS += $(patsubst %,-I %,$(INC_DIRS)) \ + $(patsubst %,-I %/include,$(LIB_DIRS)) -iquote src + +OBJECTS := $(patsubst %.c,$(BUILD)/%.c.o,$(filter %.c,$(SRC))) + +############################################################################### +# Special build rules + +# Rule to make the module file. +$(TARGET) : $(BUILD)/output.elf | $(BIN) + $(LOG) + $Q$(LD) $(BUILD)/output.elf $(LDFLAGS) -o $@ + +# Rule to make the module file. +$(BUILD)/output.elf : $(OBJECTS) | $(BIN) $(BUILD) + $(LOG) + $Q$(LD) $(OBJECTS) $(LD1FLAGS) -o $@ + +# Rule to make intermediate directory +$(BUILD) : + $Qmkdir $@ + +# Rule to make output directory +$(BIN) : + $Qmkdir $@ + +############################################################################### +# Standard build rules + +$(BUILD)/%.c.o: %.c | $(BUILD) + $(LOG) + -$Qmkdir -p $(dir $@) + $Q$(CC) -c $(CFLAGS) $< -o $@ + +############################################################################### +# Assembly listing rules + +# Rule to make assembly listing. +PHONY += list +list : $(LIST) + +# Rule to make the listing file. +%.list : $(TARGET) + $(LOG) + -$Qmkdir -p $(dir $@) + $Q$(OBJDUMP) -d $< > $@ + +############################################################################### +# Clean rule + +# Rule to clean files. +PHONY += clean +clean : + $Qrm -rf $(wildcard $(BUILD) $(BIN)) + +############################################################################### +# Phony targets + +.PHONY : $(PHONY) diff --git a/example_plugin/main.c b/example_plugin/main.c new file mode 100644 index 0000000..8a4aaa2 --- /dev/null +++ b/example_plugin/main.c @@ -0,0 +1,19 @@ +#include +#include + +WUPS_MODULE_NAME("test module"); +WUPS_MODULE_VERSION("v1.0"); +WUPS_MODULE_AUTHOR("Maschell"); +WUPS_MODULE_LICENSE("BSD"); + +int func(void); + +static int value = 15; + +static int my_func(void) +{ + int res = func(); + return 4 * value * res; +} + +WUPS_MUST_REPLACE(func,WUPS_LOADER_LIBRARY_COREINIT, my_func); diff --git a/example_plugin/makefile.mk b/example_plugin/makefile.mk new file mode 100644 index 0000000..b7fa45f --- /dev/null +++ b/example_plugin/makefile.mk @@ -0,0 +1,17 @@ +############################################################################### +# Source files + +# The source files to compile. +SRC := main.c +# Include directories +INC_DIRS := +# Library directories +LIB_DIRS := +# The names of libraries to use. +LIBS := +# The output directory for compiled results. +BIN := bin +# The name of the output file to generate. +TARGET := $(BIN)/$(notdir $(CURDIR)).mod +# C compiler flags +CFLAGS := diff --git a/wups.ld b/wups.ld new file mode 100644 index 0000000..7a60c45 --- /dev/null +++ b/wups.ld @@ -0,0 +1,23 @@ +SECTIONS { + .wups.meta : { + *(.wups.meta*) + } + .wups.load : { + *(.wups.load*) + } + .text : { + *(.text*) + } + .data : { + *(.data*) + } + .rodata : { + *(.rodata*) + } + .bss : { + *(.bss*) + } + /DISCARD/ : { + *(*) + } +} \ No newline at end of file diff --git a/wups_elf.ld b/wups_elf.ld new file mode 100644 index 0000000..064a4f9 --- /dev/null +++ b/wups_elf.ld @@ -0,0 +1,10 @@ +SECTIONS { + .wups.meta : { + bslug_meta = .; + *(.wups.meta*) + } + .wups.load : { + bslug_load = .; + *(.wups.load*) + } +} \ No newline at end of file diff --git a/wups_include/wups.h b/wups_include/wups.h new file mode 100644 index 0000000..61ef987 --- /dev/null +++ b/wups_include/wups.h @@ -0,0 +1,124 @@ +/* wups.h + * by Alex Chadwick + * + * Copyright (C) 2014, Alex Chadwick + * Modified by Maschell, 2018 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef WUPS_H_ +#define WUPS_H_ + +#include +#include + +#define WUPS_SECTION(x) __attribute__((__section__ (".wups." x))) + +typedef enum wups_loader_entry_type_t { + WUPS_LOADER_ENTRY_FUNCTION, + WUPS_LOADER_ENTRY_FUNCTION_MANDATORY, + WUPS_LOADER_ENTRY_EXPORT +} wups_loader_entry_type_t; + + +typedef enum wups_loader_library_type_t { + WUPS_LOADER_LIBRARY_COREINIT, + WUPS_LOADER_LIBRARY_GX2 +} wups_loader_library_type_t; + +typedef struct wups_loader_entry_t { + wups_loader_entry_type_t type; + union { + struct { + const char *name; + const wups_loader_library_type_t library; + const void *target; + } function; + struct { + const char *name; + const void *target; + } export; + } data; +} wups_loader_entry_t; + +#define WUPS_REPLACE(original_func, rpl_type, replace_func) \ + extern const wups_loader_entry_t wups_load_ ## original_func \ + WUPS_SECTION("load"); \ + const wups_loader_entry_t wups_load_ ## original_func = { \ + .type = WUPS_LOADER_ENTRY_FUNCTION, \ + .data = { \ + .function = { \ + .name = #original_func, \ + .library = rpl_type, \ + .target = &(replace_func) \ + } \ + } \ + } +#define WUPS_MUST_REPLACE(original_func, rpl_type, replace_func) \ + extern const wups_loader_entry_t wups_load_ ## original_func \ + WUPS_SECTION("load"); \ + const wups_loader_entry_t wups_load_ ## original_func = { \ + .type = WUPS_LOADER_ENTRY_FUNCTION_MANDATORY, \ + .data = { \ + .function = { \ + .name = #original_func, \ + .library = rpl_type, \ + .target = &(replace_func) \ + } \ + } \ + } +#define WUPS_EXPORT(symbol) \ + extern const wups_loader_entry_t wups_export_ ## symbol \ + WUPS_SECTION("load"); \ + const wups_loader_entry_t wups_export_ ## symbol = { \ + .type = WUPS_LOADER_ENTRY_EXPORT, \ + .data = { \ + .export = { \ + .name = #symbol, \ + .target = &(symbol) \ + } \ + } \ + } + +#define WUPS_META(id, value) \ + extern const char wups_meta_ ## id [] WUPS_SECTION("meta"); \ + const char wups_meta_ ## id [] = #id "=" value + +#define WUPS_MODULE_NAME(x) WUPS_META(name, x); WUPS_META(wups, "0.1") +#define WUPS_MODULE_AUTHOR(x) WUPS_META(author, x) +#define WUPS_MODULE_VERSION(x) WUPS_META(version, x) +#define WUPS_MODULE_LICENSE(x) WUPS_META(license, x) + +/* wups_game_start - first address that is part of the game's executable. + * wups_game_end - address after the end of the game's executable. + * Added in WUPS_LIB_VERSION 0.1.1 */ +extern uint8_t wups_game_start[]; +extern uint8_t wups_game_end[]; + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* WUPS_WUPS_H_ */ \ No newline at end of file