-added file loading with button configuration, make sure to check the README for instructions.

This commit is contained in:
FIX94 2016-11-14 00:18:10 +01:00
parent f68e046dae
commit e803047295
15 changed files with 491 additions and 101 deletions

View File

@ -6,75 +6,62 @@ else
ZIP = zip ZIP = zip
endif 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: setup_brainage:
rm -f *.bin @rm -f defines.s haxchi_rop.bin haxchi_rop_hook.bin
@cd hbl_loader && make && cd ..
@cp -f brainage_defs.s defines.s @cp -f brainage_defs.s defines.s
setup_kirby: setup_kirby:
rm -f *.bin @rm -f defines.s haxchi_rop.bin haxchi_rop_hook.bin
@cd hbl_loader && make && cd ..
@cp -f kirby_defs.s defines.s @cp -f kirby_defs.s defines.s
setup_yoshids: setup_yoshids:
rm -f *.bin @rm -f defines.s haxchi_rop.bin haxchi_rop_hook.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 ..
@cp -f yoshids_defs.s defines.s @cp -f yoshids_defs.s defines.s
brainage.nds: brainage.nds:
armips haxchi_rop.s @armips haxchi_rop.s
armips haxchi.s @armips haxchi.s
mv rom.nds brainage.nds @mv rom.nds brainage.nds
kirby.nds: kirby.nds:
armips haxchi_rop.s @armips haxchi_rop.s
armips haxchi.s @armips haxchi.s
mv rom.nds kirby.nds @mv rom.nds kirby.nds
yoshids.nds: yoshids.nds:
armips haxchi_rop.s @armips haxchi_rop.s
armips haxchi.s @armips haxchi.s
mv rom.nds yoshids.nds @mv rom.nds yoshids.nds
cp yoshids.nds wwtouched.nds @cp yoshids.nds wwtouched.nds
brainage_cfw.nds: brainage_cfw.nds:
armips haxchi_rop.s @armips haxchi_rop.s
armips haxchi.s @armips haxchi.s
mv rom.nds brainage_cfw.nds @mv rom.nds brainage_cfw.nds
kirby_cfw.nds: kirby_cfw.nds:
armips haxchi_rop.s @armips haxchi_rop.s
armips haxchi.s @armips haxchi.s
mv rom.nds kirby_cfw.nds @mv rom.nds kirby_cfw.nds
yoshids_cfw.nds: yoshids_cfw.nds:
armips haxchi_rop.s @armips haxchi_rop.s
armips haxchi.s @armips haxchi.s
mv rom.nds yoshids_cfw.nds @mv rom.nds yoshids_cfw.nds
cp yoshids_cfw.nds wwtouched_cfw.nds @cp yoshids_cfw.nds wwtouched_cfw.nds
brainage.zip: brainage.zip:
$(ZIP) -JXjq9 brainage.zip brainage.nds $(ZIP) -JXjq9 brainage.zip brainage.nds
@ -86,19 +73,9 @@ yoshids.zip:
$(ZIP) -JXjq9 yoshids.zip yoshids.nds $(ZIP) -JXjq9 yoshids.zip yoshids.nds
$(ZIP) -JXjq9 wwtouched.zip wwtouched.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: clean:
@rm -f *.bin defines.s brainage.nds brainage.zip kirby.nds kirby.zip wwtouched.nds wwtouched.zip yoshids.nds yoshids.zip @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 option_select && make clean && cd ..
@cd cfw_booter && make clean && cd ..
@cd hbl_loader && make clean && cd .. @cd hbl_loader && make clean && cd ..
@cd cfw_booter && make clean && cd ..
@echo "all cleaned up !" @echo "all cleaned up !"

View File

@ -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") 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: make sure to replace YOUR_GAME_TITLE_ID with one of the following:
10179A00 - JPN Brain Age
10179B00 - US Brain Age 10179B00 - US Brain Age
10179C00 - PAL Brain Training 10179C00 - PAL Brain Training
10198800 - JPN Yoshi's Island DS
10198900 - US Yoshi's Island DS 10198900 - US Yoshi's Island DS
10198A00 - PAL Yoshi's Island DS 10198A00 - PAL Yoshi's Island DS
101A1E00 - JPN WarioWare: Touched
101A1F00 - US WarioWare: Touched 101A1F00 - US WarioWare: Touched
101A2000 - PAL WarioWare: Touched 101A2000 - PAL WarioWare: Touched
101A5500 - JPN Kirby Squeak Squad
101A5600 - US Kirby Squeak Squad 101A5600 - US Kirby Squeak Squad
101A5700 - PAL Kirby Mouse Attack 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 ## contents
* hbl_loader: a loader which will load up the homebrew launcher from sd card * hbl_loader: a loader which will load up the homebrew launcher from sd card

View File

@ -6,14 +6,12 @@ CFLAGS = -std=gnu99 -O3 -nostdinc -fno-builtin
ASFLAGS = -mregnames -x assembler-with-cpp ASFLAGS = -mregnames -x assembler-with-cpp
LD = $(PREFIX)ld LD = $(PREFIX)ld
OBJCOPY = $(PREFIX)objcopy 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 OBJDUMP ?= $(PREFIX)objdump
project := . project := .
root := $(CURDIR) root := $(CURDIR)
build := $(root)/bin build := $(root)/bin
CFLAGS += -DUSE_SD_LOADER
ASFLAGS += -DUSE_SD_LOADER
FIRMWARE = 550 FIRMWARE = 550
all: clean setup main all: clean setup main
@ -36,15 +34,11 @@ main: $(CURDIR)/payload/arm_kernel_bin.h
$(AS) $(ASFLAGS) -DVER=$(FIRMWARE) -c $(project)/crt0.S $(AS) $(ASFLAGS) -DVER=$(FIRMWARE) -c $(project)/crt0.S
cp -r $(root)/*.o $(build) cp -r $(root)/*.o $(build)
rm $(root)/*.o rm $(root)/*.o
$(LD) -o code$(FIRMWARE).elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map code.map $(LD) -o cfw_booter.elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map cfw_booter.map
$(OBJCOPY) code$(FIRMWARE).elf -S -O binary ../code$(FIRMWARE).bin $(OBJCOPY) cfw_booter.elf -S -O binary ../cfw_booter.bin
clean: clean:
rm -rf $(build) payload 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_user -f $(CURDIR)/arm_user/Makefile clean
$(MAKE) --no-print-directory -C $(CURDIR)/arm_kernel -f $(CURDIR)/arm_kernel/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

View File

@ -39,8 +39,6 @@ static const char os_launch_hook[] = {
0x05, 0x0b, 0xcf, 0xfc, 0x05, 0x05, 0x99, 0x70, 0x05, 0x05, 0x99, 0x7e, 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) static unsigned int __attribute__((noinline)) disable_mmu(void)
{ {
unsigned int control_register = 0; unsigned int control_register = 0;
@ -90,8 +88,8 @@ int _main()
int i; int i;
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
if (i < 11) if (i < 31)
((char*)(0x050663B4 - 0x05000000 + 0x081C0000))[i] = sd_path[i]; ((char*)(0x050663B4 - 0x05000000 + 0x081C0000))[i] = ((char*)0x01E70000)[i];
else else
((char*)(0x050663B4 - 0x05000000 + 0x081C0000))[i] = (char)0; ((char*)(0x050663B4 - 0x05000000 + 0x081C0000))[i] = (char)0;

View File

@ -2,7 +2,9 @@
.include "defines.s" .include "defines.s"
; more useful definitions ; 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_THREAD0OBJECT equ (HAX_TARGET_ADDRESS - 0x1000)
NERD_THREAD2OBJECT equ (HAX_TARGET_ADDRESS - 0x2000) NERD_THREAD2OBJECT equ (HAX_TARGET_ADDRESS - 0x2000)
@ -221,15 +223,17 @@ rop_start:
call_func OSCODEGEN_SWITCHSECMODE, 0x0, 0x0, 0x0, 0x0 call_func OSCODEGEN_SWITCHSECMODE, 0x0, 0x0, 0x0, 0x0
; memcpy code ; memcpy code
call_func MEMCPY, CODEGEN_ADR, code, code_end - code, 0x0 call_func MEMCPY, HBL_LOADER_ADR, hbl_loader, hbl_loader_end - hbl_loader, 0x0
call_func DC_FLUSHRANGE, CODEGEN_ADR, code_end - code, 0x0, 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 ; switch codegen to RX
call_func OSCODEGEN_SWITCHSECMODE, 0x1, 0x0, 0x0, 0x0 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 ; execute hbl_loader in codegen
.word CODEGEN_ADR .word SELECTOR_ADDRESS
core0rop_end: core0rop_end:
; core 0 thread params ; core 0 thread params
@ -256,9 +260,16 @@ rop_start:
.word 0x00000010 ; thread prio .word 0x00000010 ; thread prio
.halfword 0x0004 ; thread affinity (core2) .halfword 0x0004 ; thread affinity (core2)
; hbl_loader code
code: code:
.incbin "code550.bin" .incbin "code550.bin"
code_end: code_end:
hbl_loader:
.incbin "hbl_loader.bin"
hbl_loader_end:
cfw_booter:
.incbin "cfw_booter.bin"
cfw_booter_end:
.Close .Close

View File

@ -36,15 +36,11 @@ main: sd_loader.h
$(AS) $(ASFLAGS) -DVER=$(FIRMWARE) -c $(project)/crt0.S $(AS) $(ASFLAGS) -DVER=$(FIRMWARE) -c $(project)/crt0.S
cp -r $(root)/*.o $(build) cp -r $(root)/*.o $(build)
rm $(root)/*.o rm $(root)/*.o
$(LD) -o code$(FIRMWARE).elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map code.map $(LD) -o hbl_loader.elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map hbl_loader.map
$(OBJCOPY) code$(FIRMWARE).elf -S -O binary ../code$(FIRMWARE).bin $(OBJCOPY) hbl_loader.elf -S -O binary ../hbl_loader.bin
clean: clean:
rm -rf $(build) rm -rf $(build)
rm -rf sd_loader.h 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 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

View File

@ -305,6 +305,16 @@ static void InstallMain(private_data_t *private_data)
if(section_offset > 0) if(section_offset > 0)
SC_0x25_KernelCopyData((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text, main_text_len); 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 // get the .rodata section
unsigned int main_rodata_addr = 0; unsigned int main_rodata_addr = 0;
unsigned int main_rodata_len = 0; unsigned int main_rodata_len = 0;

View File

@ -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 \ CXXFLAGS := -std=gnu++11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \
-O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE)
ASFLAGS := -mregnames ASFLAGS := -mregnames
LDFLAGS := -nostartfiles -Wl,--gc-sections LDFLAGS := -nostartfiles -Wl,--gc-sections -Xlinker -Map=fuck.map
Q := @ Q := @
MAKEFLAGS += --no-print-directory MAKEFLAGS += --no-print-directory

View File

@ -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); int status = private_data->FSGetMountSource(pClient, pCmd, 0, tempPath, -1);
if (status != 0) { 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); status = private_data->FSMount(pClient, pCmd, tempPath, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);
if(status != 0) { if(status != 0) {
private_data->OSFatal("SD mount failed."); private_data->OSFatal("-4");
} }
status = private_data->FSOpenFile(pClient, pCmd, filepath, "r", &iFd, -1); status = private_data->FSOpenFile(pClient, pCmd, filepath, "r", &iFd, -1);
if(status != 0) { if(status != 0) {
private_data->OSFatal("FSOpenFile failed."); private_data->OSFatal("-5");
} }
FSStat stat; FSStat stat;
@ -410,7 +410,7 @@ static int LoadFileToMem(private_data_t *private_data, const char *filepath, uns
if(stat.size > 0) if(stat.size > 0)
pBuffer = private_data->MEMAllocFromDefaultHeapEx((stat.size + 0x3F) & ~0x3F, 0x40); pBuffer = private_data->MEMAllocFromDefaultHeapEx((stat.size + 0x3F) & ~0x3F, 0x40);
else else
private_data->OSFatal("ELF file empty."); private_data->OSFatal("-6");
unsigned int done = 0; 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); 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) if(MAIN_ENTRY_ADDR != 0xC001C0DE)
{ {
@ -600,18 +609,18 @@ int _start(int argc, char **argv)
unsigned char *pElfBuffer = NULL; unsigned char *pElfBuffer = NULL;
unsigned int uiElfSize = 0; 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) if(!pElfBuffer)
{ {
private_data.OSFatal("Failed to load homebrew_launcher.elf"); private_data.OSFatal("-1");
} }
else else
{ {
MAIN_ENTRY_ADDR = load_elf_image(&private_data, pElfBuffer); MAIN_ENTRY_ADDR = load_elf_image(&private_data, pElfBuffer);
if(MAIN_ENTRY_ADDR == 0) if(MAIN_ENTRY_ADDR == 0)
{ {
private_data.OSFatal("Failed to load homebrew_launcher.elf"); private_data.OSFatal("-2");
} }
else else
{ {
@ -623,9 +632,14 @@ int _start(int argc, char **argv)
else else
{ {
int returnVal = ((int (*)(int, char **))MAIN_ENTRY_ADDR)(argc, argv); 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 //! exit to miimaker and restart application on re-enter of another application
if(returnVal == (int)EXIT_RELAUNCH_ON_LOAD) if(returnVal == (int)EXIT_RELAUNCH_ON_LOAD)
{ {
//! exited hbl itself, activate lock-out mechanism for safety
INT_EXIT_TO_MENU = 2;
break; break;
} }
//! exit to homebrew launcher in all other cases //! 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 was an RPX launch then launch HBL again after return
//! if an application returns and was an RPX launch then launch HBL again
if(MAIN_ENTRY_ADDR == 0xC001C0DE) if(MAIN_ENTRY_ADDR == 0xC001C0DE)
{ {
int ret = ( (int (*)(int, char **))(entry) )(argc, argv);
private_data.SYSRelaunchTitle(0, 0); private_data.SYSRelaunchTitle(0, 0);
private_data.exit(0); private_data.exit(ret);
} }
return ret; //! launch the original title with clean stack
return entry;
} }

View File

@ -11,13 +11,16 @@ SECTIONS {
KEEP(*(.kernel_code*)); KEEP(*(.kernel_code*));
} }
.data : { .data : {
*(.rodata*); *(.rodata) *(.rodata.*);
*(.data*); *(.data*);
*(.bss*); *(.bss*);
} }
.rodata1 : {
*(.rodata1) *(.rodata1.*)
}
/DISCARD/ : { /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.");

34
option_select/Makefile Normal file
View File

@ -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

31
option_select/coreinit.h Normal file
View File

@ -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 */

9
option_select/crt0.S Normal file
View File

@ -0,0 +1,9 @@
.extern __main
.globl _start
_start:
# jump to our main
bl __main
mtlr r3
blr

267
option_select/main.c Normal file
View File

@ -0,0 +1,267 @@
#include <string.h>
#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;
}

20
option_select/types.h Normal file
View File

@ -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 */