mirror of
https://github.com/wiiu-env/haxchi.git
synced 2024-11-25 09:26:54 +01:00
-added file loading with button configuration, make sure to check the README for instructions.
This commit is contained in:
parent
f68e046dae
commit
e803047295
91
Makefile
91
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 !"
|
||||
|
26
README.md
26
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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
23
haxchi_rop.s
23
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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,8 +564,17 @@ 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -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.");
|
||||
|
34
option_select/Makefile
Normal file
34
option_select/Makefile
Normal 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
31
option_select/coreinit.h
Normal 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
9
option_select/crt0.S
Normal 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
267
option_select/main.c
Normal 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
20
option_select/types.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user