diff --git a/Makefile b/Makefile index cb266ad..079c95f 100644 --- a/Makefile +++ b/Makefile @@ -6,75 +6,62 @@ else ZIP = zip endif -all: brainage kirby yoshids brainage.zip kirby.zip yoshids.zip brainage_cfw.zip kirby_cfw.zip yoshids_cfw.zip +all: setup brainage kirby yoshids brainage.zip kirby.zip yoshids.zip -brainage: setup_brainage brainage.nds setup_brainage_cfw brainage_cfw.nds +brainage: setup_brainage brainage.nds -kirby: setup_kirby kirby.nds setup_kirby_cfw kirby_cfw.nds +kirby: setup_kirby kirby.nds -yoshids: setup_yoshids yoshids.nds setup_yoshids_cfw yoshids_cfw.nds +yoshids: setup_yoshids yoshids.nds + +setup: + @cd option_select && make && cd .. + @cd hbl_loader && make && cd .. + @cd cfw_booter && make && cd .. setup_brainage: - rm -f *.bin - @cd hbl_loader && make && cd .. + @rm -f defines.s haxchi_rop.bin haxchi_rop_hook.bin @cp -f brainage_defs.s defines.s setup_kirby: - rm -f *.bin - @cd hbl_loader && make && cd .. + @rm -f defines.s haxchi_rop.bin haxchi_rop_hook.bin @cp -f kirby_defs.s defines.s setup_yoshids: - rm -f *.bin - @cd hbl_loader && make && cd .. - @cp -f yoshids_defs.s defines.s - -setup_brainage_cfw: - rm -f *.bin - @cd cfw_booter && make && cd .. - @cp -f brainage_defs.s defines.s - -setup_kirby_cfw: - rm -f *.bin - @cd cfw_booter && make && cd .. - @cp -f kirby_defs.s defines.s - -setup_yoshids_cfw: - rm -f *.bin - @cd cfw_booter && make && cd .. + @rm -f defines.s haxchi_rop.bin haxchi_rop_hook.bin @cp -f yoshids_defs.s defines.s brainage.nds: - armips haxchi_rop.s - armips haxchi.s - mv rom.nds brainage.nds + @armips haxchi_rop.s + @armips haxchi.s + @mv rom.nds brainage.nds kirby.nds: - armips haxchi_rop.s - armips haxchi.s - mv rom.nds kirby.nds + @armips haxchi_rop.s + @armips haxchi.s + @mv rom.nds kirby.nds yoshids.nds: - armips haxchi_rop.s - armips haxchi.s - mv rom.nds yoshids.nds - cp yoshids.nds wwtouched.nds + @armips haxchi_rop.s + @armips haxchi.s + @mv rom.nds yoshids.nds + @cp yoshids.nds wwtouched.nds brainage_cfw.nds: - armips haxchi_rop.s - armips haxchi.s - mv rom.nds brainage_cfw.nds + @armips haxchi_rop.s + @armips haxchi.s + @mv rom.nds brainage_cfw.nds kirby_cfw.nds: - armips haxchi_rop.s - armips haxchi.s - mv rom.nds kirby_cfw.nds + @armips haxchi_rop.s + @armips haxchi.s + @mv rom.nds kirby_cfw.nds yoshids_cfw.nds: - armips haxchi_rop.s - armips haxchi.s - mv rom.nds yoshids_cfw.nds - cp yoshids_cfw.nds wwtouched_cfw.nds + @armips haxchi_rop.s + @armips haxchi.s + @mv rom.nds yoshids_cfw.nds + @cp yoshids_cfw.nds wwtouched_cfw.nds brainage.zip: $(ZIP) -JXjq9 brainage.zip brainage.nds @@ -86,19 +73,9 @@ yoshids.zip: $(ZIP) -JXjq9 yoshids.zip yoshids.nds $(ZIP) -JXjq9 wwtouched.zip wwtouched.nds -brainage_cfw.zip: - $(ZIP) -JXjq9 brainage_cfw.zip brainage_cfw.nds - -kirby_cfw.zip: - $(ZIP) -JXjq9 kirby_cfw.zip kirby_cfw.nds - -yoshids_cfw.zip: - $(ZIP) -JXjq9 yoshids_cfw.zip yoshids_cfw.nds - $(ZIP) -JXjq9 wwtouched_cfw.zip wwtouched_cfw.nds - clean: @rm -f *.bin defines.s brainage.nds brainage.zip kirby.nds kirby.zip wwtouched.nds wwtouched.zip yoshids.nds yoshids.zip - @rm -f brainage_cfw.nds brainage_cfw.zip kirby_cfw.nds kirby_cfw.zip wwtouched_cfw.nds wwtouched_cfw.zip yoshids_cfw.nds yoshids_cfw.zip - @cd cfw_booter && make clean && cd .. + @cd option_select && make clean && cd .. @cd hbl_loader && make clean && cd .. + @cd cfw_booter && make clean && cd .. @echo "all cleaned up !" diff --git a/README.md b/README.md index e911a71..b3683e4 100644 --- a/README.md +++ b/README.md @@ -13,16 +13,42 @@ of course, using wupclient to install haxchi permanently requires that redNAND b ``` w.up("rom.zip", "/vol/storage_usb01/usr/title/00050000/YOUR_GAME_TITLE_ID/content/0010/rom.zip") ``` + +To upload a config.txt as well you will have to do the following if the title is installed on NAND: +``` + w.up("config.txt", "/vol/storage_mlc01/usr/title/00050000/YOUR_GAME_TITLE_ID/content/config.txt") + w.chmod("/vol/storage_mlc01/usr/title/00050000/YOUR_GAME_TITLE_ID/content/config.txt", 0x644) +``` +and for the title being installed to USB you do the following: +``` + w.up("config.txt", "/vol/storage_usb01/usr/title/00050000/YOUR_GAME_TITLE_ID/content/config.txt") + w.chmod("/vol/storage_usb01/usr/title/00050000/YOUR_GAME_TITLE_ID/content/config.txt", 0x644) +``` + make sure to replace YOUR_GAME_TITLE_ID with one of the following: +10179A00 - JPN Brain Age 10179B00 - US Brain Age 10179C00 - PAL Brain Training +10198800 - JPN Yoshi's Island DS 10198900 - US Yoshi's Island DS 10198A00 - PAL Yoshi's Island DS +101A1E00 - JPN WarioWare: Touched 101A1F00 - US WarioWare: Touched 101A2000 - PAL WarioWare: Touched +101A5500 - JPN Kirby Squeak Squad 101A5600 - US Kirby Squeak Squad 101A5700 - PAL Kirby Mouse Attack +a config.txt can look like this for example: +``` +a=fw.img +b=rednand/fw.img +x=wiiu/apps/ftpiiu/ftpiiu.elf +down=wiiu/apps/snes9x2010_libretro/snes9x2010_libretro.elf +default=wiiu/apps/homebrew_launcher/homebrew_launcher.elf +``` +please note though that if you want to load a fw.img the name HAS to be named fw.img in whatever folder you use, nothing else will work. + ## contents * hbl_loader: a loader which will load up the homebrew launcher from sd card diff --git a/cfw_booter/Makefile b/cfw_booter/Makefile index e1b5d1b..bbd7543 100644 --- a/cfw_booter/Makefile +++ b/cfw_booter/Makefile @@ -6,14 +6,12 @@ CFLAGS = -std=gnu99 -O3 -nostdinc -fno-builtin ASFLAGS = -mregnames -x assembler-with-cpp LD = $(PREFIX)ld OBJCOPY = $(PREFIX)objcopy -LDFLAGS=-Ttext 1800000 -L$(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2 -lgcc +LDFLAGS=-Ttext 180C000 -L$(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2 -lgcc OBJDUMP ?= $(PREFIX)objdump project := . root := $(CURDIR) build := $(root)/bin -CFLAGS += -DUSE_SD_LOADER -ASFLAGS += -DUSE_SD_LOADER FIRMWARE = 550 all: clean setup main @@ -36,15 +34,11 @@ main: $(CURDIR)/payload/arm_kernel_bin.h $(AS) $(ASFLAGS) -DVER=$(FIRMWARE) -c $(project)/crt0.S cp -r $(root)/*.o $(build) rm $(root)/*.o - $(LD) -o code$(FIRMWARE).elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map code.map - $(OBJCOPY) code$(FIRMWARE).elf -S -O binary ../code$(FIRMWARE).bin + $(LD) -o cfw_booter.elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map cfw_booter.map + $(OBJCOPY) cfw_booter.elf -S -O binary ../cfw_booter.bin clean: rm -rf $(build) payload - rm -rf code$(FIRMWARE).elf code.map + rm -rf cfw_booter.elf cfw_booter.map $(MAKE) --no-print-directory -C $(CURDIR)/arm_user -f $(CURDIR)/arm_user/Makefile clean $(MAKE) --no-print-directory -C $(CURDIR)/arm_kernel -f $(CURDIR)/arm_kernel/Makefile clean - -print_stats: - @echo - @echo "code size : loadiine =>" `$(OBJDUMP) -h ../loadiine.elf | awk '/.kernel_code|.text|.menu_magic|.loader_magic|.fs_method_calls|.rodata|.data|.sdata|.bss|.sbss|.fs_magic/ { sum+=strtonum("0x"$$3) } END {print sum}'` / 7530312 diff --git a/cfw_booter/arm_kernel/source/main.c b/cfw_booter/arm_kernel/source/main.c index e810c21..cfd7b4e 100644 --- a/cfw_booter/arm_kernel/source/main.c +++ b/cfw_booter/arm_kernel/source/main.c @@ -39,8 +39,6 @@ static const char os_launch_hook[] = { 0x05, 0x0b, 0xcf, 0xfc, 0x05, 0x05, 0x99, 0x70, 0x05, 0x05, 0x99, 0x7e, }; -static const char sd_path[] = "/vol/sdcard"; - static unsigned int __attribute__((noinline)) disable_mmu(void) { unsigned int control_register = 0; @@ -90,8 +88,8 @@ int _main() int i; for (i = 0; i < 32; i++) - if (i < 11) - ((char*)(0x050663B4 - 0x05000000 + 0x081C0000))[i] = sd_path[i]; + if (i < 31) + ((char*)(0x050663B4 - 0x05000000 + 0x081C0000))[i] = ((char*)0x01E70000)[i]; else ((char*)(0x050663B4 - 0x05000000 + 0x081C0000))[i] = (char)0; diff --git a/haxchi_rop.s b/haxchi_rop.s index 58d8edc..39496f8 100644 --- a/haxchi_rop.s +++ b/haxchi_rop.s @@ -2,7 +2,9 @@ .include "defines.s" ; more useful definitions -CODEGEN_ADR equ (0x01800000) +HBL_LOADER_ADR equ (0x01800000) +SELECTOR_ADDRESS equ (0x01808000) +CFW_BOOTER_ADR equ (0x0180C000) NERD_THREAD0OBJECT equ (HAX_TARGET_ADDRESS - 0x1000) NERD_THREAD2OBJECT equ (HAX_TARGET_ADDRESS - 0x2000) @@ -221,15 +223,17 @@ rop_start: call_func OSCODEGEN_SWITCHSECMODE, 0x0, 0x0, 0x0, 0x0 ; memcpy code - call_func MEMCPY, CODEGEN_ADR, code, code_end - code, 0x0 - call_func DC_FLUSHRANGE, CODEGEN_ADR, code_end - code, 0x0, 0x0 + call_func MEMCPY, HBL_LOADER_ADR, hbl_loader, hbl_loader_end - hbl_loader, 0x0 + call_func MEMCPY, SELECTOR_ADDRESS, code, code_end - code, 0x0 + call_func MEMCPY, CFW_BOOTER_ADR, cfw_booter, cfw_booter_end - cfw_booter, 0x0 + call_func DC_FLUSHRANGE, HBL_LOADER_ADR, 0xE000, 0x0, 0x0 ; switch codegen to RX call_func OSCODEGEN_SWITCHSECMODE, 0x1, 0x0, 0x0, 0x0 - call_func IC_INVALIDATERANGE, CODEGEN_ADR, code_end - code, 0x0, 0x0 + call_func IC_INVALIDATERANGE, HBL_LOADER_ADR, 0xE000, 0x0, 0x0 ; execute hbl_loader in codegen - .word CODEGEN_ADR + .word SELECTOR_ADDRESS core0rop_end: ; core 0 thread params @@ -256,9 +260,16 @@ rop_start: .word 0x00000010 ; thread prio .halfword 0x0004 ; thread affinity (core2) - ; hbl_loader code code: .incbin "code550.bin" code_end: + hbl_loader: + .incbin "hbl_loader.bin" + hbl_loader_end: + + cfw_booter: + .incbin "cfw_booter.bin" + cfw_booter_end: + .Close diff --git a/hbl_loader/Makefile b/hbl_loader/Makefile index fd7092b..efa87e3 100644 --- a/hbl_loader/Makefile +++ b/hbl_loader/Makefile @@ -36,15 +36,11 @@ main: sd_loader.h $(AS) $(ASFLAGS) -DVER=$(FIRMWARE) -c $(project)/crt0.S cp -r $(root)/*.o $(build) rm $(root)/*.o - $(LD) -o code$(FIRMWARE).elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map code.map - $(OBJCOPY) code$(FIRMWARE).elf -S -O binary ../code$(FIRMWARE).bin + $(LD) -o hbl_loader.elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map hbl_loader.map + $(OBJCOPY) hbl_loader.elf -S -O binary ../hbl_loader.bin clean: rm -rf $(build) rm -rf sd_loader.h - rm -rf code$(FIRMWARE).elf code.map + rm -rf hbl_loader.elf hbl_loader.map make clean -C sd_loader - -print_stats: - @echo - @echo "code size : loadiine =>" `$(OBJDUMP) -h ../loadiine.elf | awk '/.kernel_code|.text|.menu_magic|.loader_magic|.fs_method_calls|.rodata|.data|.sdata|.bss|.sbss|.fs_magic/ { sum+=strtonum("0x"$$3) } END {print sum}'` / 7530312 diff --git a/hbl_loader/launcher.c b/hbl_loader/launcher.c index b20d5d8..a53a5ea 100644 --- a/hbl_loader/launcher.c +++ b/hbl_loader/launcher.c @@ -305,6 +305,16 @@ static void InstallMain(private_data_t *private_data) if(section_offset > 0) SC_0x25_KernelCopyData((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text, main_text_len); + // get the .rodata1 section + unsigned int main_rodata1_addr = 0; + unsigned int main_rodata1_len = 0; + section_offset = get_section(private_data, private_data->data_elf, ".rodata1", &main_rodata1_len, &main_rodata1_addr, 0); + if(section_offset > 0) + { + /* Copy main rodata to memory */ + SC_0x25_KernelCopyData((void*)(DATA_RW_BASE_OFFSET + main_rodata1_addr), (void*)0xF5E70000, main_rodata1_len); + } + // get the .rodata section unsigned int main_rodata_addr = 0; unsigned int main_rodata_len = 0; diff --git a/hbl_loader/sd_loader/Makefile b/hbl_loader/sd_loader/Makefile index a59f8a6..1f8cf29 100644 --- a/hbl_loader/sd_loader/Makefile +++ b/hbl_loader/sd_loader/Makefile @@ -40,7 +40,7 @@ CFLAGS := -std=gnu11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math -fno-built CXXFLAGS := -std=gnu++11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) ASFLAGS := -mregnames -LDFLAGS := -nostartfiles -Wl,--gc-sections +LDFLAGS := -nostartfiles -Wl,--gc-sections -Xlinker -Map=fuck.map Q := @ MAKEFLAGS += --no-print-directory diff --git a/hbl_loader/sd_loader/src/entry.c b/hbl_loader/sd_loader/src/entry.c index 5d7db8f..767c72b 100644 --- a/hbl_loader/sd_loader/src/entry.c +++ b/hbl_loader/sd_loader/src/entry.c @@ -388,16 +388,16 @@ static int LoadFileToMem(private_data_t *private_data, const char *filepath, uns int status = private_data->FSGetMountSource(pClient, pCmd, 0, tempPath, -1); if (status != 0) { - private_data->OSFatal("FSGetMountSource failed."); + private_data->OSFatal("-3"); } status = private_data->FSMount(pClient, pCmd, tempPath, mountPath, FS_MAX_MOUNTPATH_SIZE, -1); if(status != 0) { - private_data->OSFatal("SD mount failed."); + private_data->OSFatal("-4"); } status = private_data->FSOpenFile(pClient, pCmd, filepath, "r", &iFd, -1); if(status != 0) { - private_data->OSFatal("FSOpenFile failed."); + private_data->OSFatal("-5"); } FSStat stat; @@ -410,7 +410,7 @@ static int LoadFileToMem(private_data_t *private_data, const char *filepath, uns if(stat.size > 0) pBuffer = private_data->MEMAllocFromDefaultHeapEx((stat.size + 0x3F) & ~0x3F, 0x40); else - private_data->OSFatal("ELF file empty."); + private_data->OSFatal("-6"); unsigned int done = 0; @@ -564,9 +564,18 @@ static void loadFunctionPointers(private_data_t * private_data) OS_FIND_EXPORT(sysapp_handle, "SYSRelaunchTitle", private_data->SYSRelaunchTitle); } -int _start(int argc, char **argv) +extern const char PROVIDED_ELF_LAUNCH_PATH; +extern int INT_EXIT_TO_MENU; + +unsigned int _main(int argc, char **argv) { - private_data_t private_data; + unsigned int entry = *(unsigned int*)OS_SPECIFICS->addr_OSTitle_main_entry; + + //! force launch normal title every time (safety lock-out mechanism) + if(INT_EXIT_TO_MENU == 2) + return entry; + + private_data_t private_data; if(MAIN_ENTRY_ADDR != 0xC001C0DE) { @@ -600,18 +609,18 @@ int _start(int argc, char **argv) unsigned char *pElfBuffer = NULL; unsigned int uiElfSize = 0; - LoadFileToMem(&private_data, CAFE_OS_SD_PATH WIIU_PATH "/apps/homebrew_launcher/homebrew_launcher.elf", &pElfBuffer, &uiElfSize); + LoadFileToMem(&private_data, &PROVIDED_ELF_LAUNCH_PATH, &pElfBuffer, &uiElfSize); if(!pElfBuffer) { - private_data.OSFatal("Failed to load homebrew_launcher.elf"); + private_data.OSFatal("-1"); } else { MAIN_ENTRY_ADDR = load_elf_image(&private_data, pElfBuffer); if(MAIN_ENTRY_ADDR == 0) { - private_data.OSFatal("Failed to load homebrew_launcher.elf"); + private_data.OSFatal("-2"); } else { @@ -623,9 +632,14 @@ int _start(int argc, char **argv) else { int returnVal = ((int (*)(int, char **))MAIN_ENTRY_ADDR)(argc, argv); + //! launched custom elf once, now activate lock-out mechanism for safety + if(INT_EXIT_TO_MENU == 1) + INT_EXIT_TO_MENU = 2; //! exit to miimaker and restart application on re-enter of another application if(returnVal == (int)EXIT_RELAUNCH_ON_LOAD) { + //! exited hbl itself, activate lock-out mechanism for safety + INT_EXIT_TO_MENU = 2; break; } //! exit to homebrew launcher in all other cases @@ -640,13 +654,13 @@ int _start(int argc, char **argv) } } - int ret = ( (int (*)(int, char **))(*(unsigned int*)OS_SPECIFICS->addr_OSTitle_main_entry) )(argc, argv); - - //! if an application returns and was an RPX launch then launch HBL again + //! if an application was an RPX launch then launch HBL again after return if(MAIN_ENTRY_ADDR == 0xC001C0DE) { + int ret = ( (int (*)(int, char **))(entry) )(argc, argv); private_data.SYSRelaunchTitle(0, 0); - private_data.exit(0); + private_data.exit(ret); } - return ret; + //! launch the original title with clean stack + return entry; } diff --git a/hbl_loader/sd_loader/src/link.ld b/hbl_loader/sd_loader/src/link.ld index 1d82ead..d179265 100644 --- a/hbl_loader/sd_loader/src/link.ld +++ b/hbl_loader/sd_loader/src/link.ld @@ -11,13 +11,16 @@ SECTIONS { KEEP(*(.kernel_code*)); } .data : { - *(.rodata*); + *(.rodata) *(.rodata.*); *(.data*); *(.bss*); } + .rodata1 : { + *(.rodata1) *(.rodata1.*) + } /DISCARD/ : { *(*); } } -ASSERT((SIZEOF(.text) + SIZEOF(.data)) < 0x1300, "Memory overlapping with main elf."); +ASSERT((SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata1)) <= 0x1300, "Memory overlapping with main elf."); diff --git a/option_select/Makefile b/option_select/Makefile new file mode 100644 index 0000000..f57878a --- /dev/null +++ b/option_select/Makefile @@ -0,0 +1,34 @@ +PATH := $(DEVKITPPC)/bin:$(PATH) +PREFIX ?= powerpc-eabi- +CC = $(PREFIX)gcc +AS = $(PREFIX)gcc +CFLAGS = -std=gnu99 -O3 -nostdinc -fno-builtin -I$(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2/include -I$(DEVKITPPC)/powerpc-eabi/include +ASFLAGS = -mregnames -x assembler-with-cpp +LD = $(PREFIX)ld +OBJCOPY = $(PREFIX)objcopy +LDFLAGS=-Ttext 1808000 -L$(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2 -L$(DEVKITPPC)/powerpc-eabi/lib -lgcc -lc +OBJDUMP ?= $(PREFIX)objdump +project := . +root := $(CURDIR) +build := $(root)/bin + +CFLAGS += -DUSE_SD_LOADER +ASFLAGS += -DUSE_SD_LOADER +FIRMWARE = 550 + +all: clean setup main + +setup: + mkdir -p $(root)/bin/ + +main: + $(CC) $(CFLAGS) -DVER=$(FIRMWARE) -c $(project)/main.c + $(AS) $(ASFLAGS) -DVER=$(FIRMWARE) -c $(project)/crt0.S + cp -r $(root)/*.o $(build) + rm $(root)/*.o + $(LD) -o code$(FIRMWARE).elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map code.map + $(OBJCOPY) code$(FIRMWARE).elf -S -O binary ../code$(FIRMWARE).bin + +clean: + rm -rf $(build) + rm -rf code$(FIRMWARE).elf code.map diff --git a/option_select/coreinit.h b/option_select/coreinit.h new file mode 100644 index 0000000..cf9943e --- /dev/null +++ b/option_select/coreinit.h @@ -0,0 +1,31 @@ +//Taken from libwiius coreinit.h + +#ifndef COREINIT_H +#define COREINIT_H + +#define OSDynLoad_Acquire ((void (*)(char* rpl, unsigned int *handle))0x0102A3B4) +#define OSDynLoad_FindExport ((void (*)(unsigned int handle, int isdata, char *symbol, void *address))0x0102B828) +#define OSFatal ((void (*)(char* msg))0x01031618) +#define __os_snprintf ((int(*)(char* s, int n, const char * format, ... ))0x0102F160) + +typedef struct OSContext +{ + /* OSContext identifier */ + uint32_t tag1; + uint32_t tag2; + + /* GPRs */ + uint32_t gpr[32]; + + /* Special registers */ + uint32_t cr; + uint32_t lr; + uint32_t ctr; + uint32_t xer; + + /* Initial PC and MSR */ + uint32_t srr0; + uint32_t srr1; +} OSContext; + +#endif /* COREINIT_H */ \ No newline at end of file diff --git a/option_select/crt0.S b/option_select/crt0.S new file mode 100644 index 0000000..2ff35ce --- /dev/null +++ b/option_select/crt0.S @@ -0,0 +1,9 @@ + + .extern __main + .globl _start + +_start: + # jump to our main + bl __main + mtlr r3 + blr diff --git a/option_select/main.c b/option_select/main.c new file mode 100644 index 0000000..fa5b9d1 --- /dev/null +++ b/option_select/main.c @@ -0,0 +1,267 @@ +#include +#include "types.h" +#include "coreinit.h" + +typedef struct +{ + float x,y; +} Vec2D; + +typedef struct +{ + uint16_t x, y; /* Touch coordinates */ + uint16_t touched; /* 1 = Touched, 0 = Not touched */ + uint16_t invalid; /* 0 = All valid, 1 = X invalid, 2 = Y invalid, 3 = Both invalid? */ +} VPADTPData; + +typedef struct +{ + uint32_t btns_h; /* Held buttons */ + uint32_t btns_d; /* Buttons that are pressed at that instant */ + uint32_t btns_r; /* Released buttons */ + Vec2D lstick, rstick; /* Each contains 4-byte X and Y components */ + char unknown1c[0x52 - 0x1c]; /* Contains accelerometer and gyroscope data somewhere */ + VPADTPData tpdata; /* Normal touchscreen data */ + VPADTPData tpdata1; /* Modified touchscreen data 1 */ + VPADTPData tpdata2; /* Modified touchscreen data 2 */ + char unknown6a[0xa0 - 0x6a]; + uint8_t volume; + uint8_t battery; /* 0 to 6 */ + uint8_t unk_volume; /* One less than volume */ + char unknowna4[0xac - 0xa4]; +} VPADData; + +#define BUTTON_A 0x8000 +#define BUTTON_B 0x4000 +#define BUTTON_X 0x2000 +#define BUTTON_Y 0x1000 +#define BUTTON_LEFT 0x0800 +#define BUTTON_RIGHT 0x0400 +#define BUTTON_UP 0x0200 +#define BUTTON_DOWN 0x0100 +#define BUTTON_ZL 0x0080 +#define BUTTON_ZR 0x0040 +#define BUTTON_L 0x0020 +#define BUTTON_R 0x0010 +#define BUTTON_PLUS 0x0008 +#define BUTTON_MINUS 0x0004 +#define BUTTON_HOME 0x0002 +#define BUTTON_SYNC 0x0001 + +typedef struct +{ + int val; + char txt[12]; +} config_select; + +static const config_select sel[17] = { + {BUTTON_A,"a="}, + {BUTTON_B,"b="}, + {BUTTON_X,"x="}, + {BUTTON_Y,"y="}, + {BUTTON_LEFT,"left="}, + {BUTTON_RIGHT,"right="}, + {BUTTON_UP,"up="}, + {BUTTON_DOWN,"down="}, + {BUTTON_ZL,"zl="}, + {BUTTON_ZR,"zr="}, + {BUTTON_L,"l="}, + {BUTTON_R,"r="}, + {BUTTON_PLUS,"plus="}, + {BUTTON_MINUS,"minus="}, + {BUTTON_HOME,"home="}, + {BUTTON_SYNC,"sync="}, + {0,"default="}, +}; + +typedef struct +{ + uint32_t flag; + uint32_t permission; + uint32_t owner_id; + uint32_t group_id; + uint32_t size; + uint32_t alloc_size; + uint64_t quota_size; + uint32_t ent_id; + uint64_t ctime; + uint64_t mtime; + uint8_t attributes[48]; +} __attribute__((packed)) FSStat; + +#define MIN(a, b) (((a)>(b))?(b):(a)) + +uint32_t __main(void) +{ + unsigned int coreinit_handle; + OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); + unsigned int *pMEMAllocFromDefaultHeapEx; + unsigned int *pMEMAllocFromDefaultHeap; + unsigned int *pMEMFreeToDefaultHeap; + OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeapEx", &pMEMAllocFromDefaultHeapEx); + OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeap", &pMEMAllocFromDefaultHeap); + OSDynLoad_FindExport(coreinit_handle, 1, "MEMFreeToDefaultHeap", &pMEMFreeToDefaultHeap); + void*(*MEMAllocFromDefaultHeapEx)(int size, int align) = (void*)(*pMEMAllocFromDefaultHeapEx); + void*(*MEMAllocFromDefaultHeap)(int size) = (void*)(*pMEMAllocFromDefaultHeap); + void(*MEMFreeToDefaultHeap)(void *ptr) = (void*)(*pMEMFreeToDefaultHeap); + + void* (*OSAllocFromSystem)(uint32_t size, int align); + void (*OSFreeToSystem)(void *ptr); + OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); + OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem); + + int hbl = 1; + //default path goes to HBL + strcpy((void*)0xF5E70000,"/vol/external01/wiiu/apps/homebrew_launcher/homebrew_launcher.elf"); + + int iFd = -1; + void *pClient = OSAllocFromSystem(0x1700,4); + void *pCmd = OSAllocFromSystem(0xA80,4); + void *pBuffer = NULL; + + void (*DCStoreRange)(void *buffer, uint32_t length); + OSDynLoad_FindExport(coreinit_handle, 0, "DCStoreRange", &DCStoreRange); + + int(*FSInit)(void); + int(*FSAddClientEx)(void *pClient, int unk_zero_param, int errHandling); + int(*FSDelClient)(void *pClient); + void(*FSInitCmdBlock)(void *pCmd); + int(*FSOpenFile)(void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling); + int(*FSGetStatFile)(void *pClient, void *pCmd, int fd, void *buffer, int error); + int(*FSReadFile)(void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling); + int(*FSCloseFile)(void *pClient, void *pCmd, int fd, int errHandling); + + OSDynLoad_FindExport(coreinit_handle, 0, "FSInit", &FSInit); + OSDynLoad_FindExport(coreinit_handle, 0, "FSInitCmdBlock", &FSInitCmdBlock); + OSDynLoad_FindExport(coreinit_handle, 0, "FSAddClientEx", &FSAddClientEx); + OSDynLoad_FindExport(coreinit_handle, 0, "FSDelClient", &FSDelClient); + OSDynLoad_FindExport(coreinit_handle, 0, "FSOpenFile", &FSOpenFile); + OSDynLoad_FindExport(coreinit_handle, 0, "FSGetStatFile", &FSGetStatFile); + OSDynLoad_FindExport(coreinit_handle, 0, "FSReadFile", &FSReadFile); + OSDynLoad_FindExport(coreinit_handle, 0, "FSCloseFile", &FSCloseFile); + + FSInit(); + FSInitCmdBlock(pCmd); + FSAddClientEx(pClient, 0, -1); + FSOpenFile(pClient, pCmd, "/vol/content/config.txt", "r", &iFd, -1); + if(iFd < 0) + goto fileEnd; + FSStat stat; + stat.size = 0; + + FSGetStatFile(pClient, pCmd, iFd, &stat, -1); + + if(stat.size > 0) + { + pBuffer = OSAllocFromSystem(stat.size+1,0x40); + memset(pBuffer,0,stat.size+1); + } + else + goto fileEnd; + + unsigned int done = 0; + + while(done < stat.size) + { + int readBytes = FSReadFile(pClient, pCmd, pBuffer + done, 1, stat.size - done, iFd, 0, -1); + if(readBytes <= 0) { + break; + } + done += readBytes; + } + + unsigned int vpad_handle; + OSDynLoad_Acquire("vpad.rpl", &vpad_handle); + int(*VPADRead)(int controller, VPADData *buffer, unsigned int num, int *error); + OSDynLoad_FindExport(vpad_handle, 0, "VPADRead", &VPADRead); + + char *fList = (char*)pBuffer; + + int error; + VPADData vpad_data; + VPADRead(0, &vpad_data, 1, &error); + char FnameChar[256]; + memset(FnameChar,0,256); + int i; + for(i = 0; i < 17; i++) + { + if((vpad_data.btns_h & sel[i].val) || (sel[i].val == 0)) + { + char *n = strstr(fList,sel[i].txt); + if(n) + { + char *fEnd = NULL; + char *fName = n+strlen(sel[i].txt); + char *fEndR = strchr(fName,'\r'); + char *fEndN = strchr(fName,'\n'); + if(fEndR) + { + if(fEndN && fEndN < fEndR) + fEnd = fEndN; + else + fEnd = fEndR; + } + else if(fEndN) + { + if(fEndR && fEndR < fEndN) + fEnd = fEndR; + else + fEnd = fEndN; + } + else + fEnd = fName+strlen(fName); + if(fEnd && fName < fEnd) + { + int fLen = MIN(fEnd-fName,255); + memcpy(FnameChar, fName, fLen); + if(memcmp(FnameChar+fLen-6,"fw.img",7) == 0) + { + if(FnameChar[0] == '/' && fLen > 7 && *(FnameChar+fLen-7) == '/') + { + *(FnameChar+fLen-7) = '\0'; + __os_snprintf((void*)0xF5E70000,160,"/vol/sdcard%s",FnameChar); + } + else if(FnameChar[0] != '/' && fLen > 6 && *(FnameChar+fLen-7) == '/') + { + *(FnameChar+fLen-7) = '\0'; + __os_snprintf((void*)0xF5E70000,160,"/vol/sdcard/%s",FnameChar); + } + else + __os_snprintf((void*)0xF5E70000,160,"/vol/sdcard"); + hbl = 0; + break; + } + else if(memcmp(FnameChar+fLen-4,".elf",5) == 0) + { + if(FnameChar[0] == '/') + __os_snprintf((void*)0xF5E70000,80,"/vol/external01%s",FnameChar); + else + __os_snprintf((void*)0xF5E70000,80,"/vol/external01/%s",FnameChar); + break; + } + } + } + } + } +fileEnd: + if(pClient && pCmd) + { + if(iFd >= 0) + FSCloseFile(pClient, pCmd, iFd, -1); + FSDelClient(pClient); + OSFreeToSystem(pClient); + OSFreeToSystem(pCmd); + } + if(pBuffer) + OSFreeToSystem(pBuffer); + if(hbl) + { + if(strstr((char*)0xF5E70000, "/homebrew_launcher.elf") != NULL) + *(int*)0xF5E70050 = 0; //return to hbl + else + *(int*)0xF5E70050 = 1; //return to menu + } + DCStoreRange((void*)0xF5E70000,0xA0); + uint32_t entry = (hbl ? 0x01800000 : 0x0180C000); + return entry; +} diff --git a/option_select/types.h b/option_select/types.h new file mode 100644 index 0000000..828591e --- /dev/null +++ b/option_select/types.h @@ -0,0 +1,20 @@ +#ifndef TYPES_H +#define TYPES_H + +typedef unsigned long long uint64_t; +typedef long long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; + +typedef uint32_t size_t; + +typedef _Bool bool; +#define true 1 +#define false 0 +#define null 0 + +#endif /* TYPES_H */