diff --git a/Makefile.wiiu b/Makefile.wiiu index 182d2ddd33..89f12510cc 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -14,6 +14,7 @@ OBJ += wiiu/system/exception_handler.o OBJ += wiiu/fs/sd_fat_devoptab.o OBJ += wiiu/fs/fs_utils.o OBJ += wiiu/tex_shader.o +OBJ += wiiu/hbl.o DEFINES := diff --git a/Makefile.wiiu.salamander b/Makefile.wiiu.salamander new file mode 100644 index 0000000000..66e406752d --- /dev/null +++ b/Makefile.wiiu.salamander @@ -0,0 +1,176 @@ +TARGET := retroarch_wiiu_salamander +BUILD_HBL_ELF = 1 +BUILD_RPX = 1 +DEBUG = 0 + +PC_DEVELOPMENT_IP_ADDRESS = +PC_DEVELOPMENT_TCP_PORT = + +OBJ := +OBJ += wiiu/system/memory.o +OBJ += wiiu/system/exception_handler.o +OBJ += wiiu/fs/sd_fat_devoptab.o +OBJ += wiiu/fs/fs_utils.o +OBJ += wiiu/hbl.o +OBJ += frontend/frontend_salamander.o +OBJ += frontend/frontend_driver.o +OBJ += frontend/drivers/platform_wiiu.o +OBJ += frontend/drivers/platform_null.o +OBJ += libretro-common/compat/compat_strcasestr.o +OBJ += libretro-common/file/file_path.o +OBJ += libretro-common/string/stdstring.o +OBJ += libretro-common/lists/string_list.o +OBJ += libretro-common/lists/dir_list.o +OBJ += libretro-common/file/retro_dirent.o +OBJ += libretro-common/compat/compat_strl.o +OBJ += libretro-common/file/config_file.o +OBJ += libretro-common/streams/file_stream.o +OBJ += libretro-common/file/retro_stat.o +OBJ += libretro-common/hash/rhash.o +OBJ += file_path_str.o +OBJ += verbosity.o + +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 + +export PATH := $(PATH):$(DEVKITPPC)/bin + +PREFIX := powerpc-eabi- + +CC := $(PREFIX)gcc +CXX := $(PREFIX)g++ +AS := $(PREFIX)as +AR := $(PREFIX)ar +OBJCOPY := $(PREFIX)objcopy +STRIP := $(PREFIX)strip +NM := $(PREFIX)nm +LD := $(CXX) + +ELF2RPL := wiiu/wut/elf2rpl/elf2rpl + +ifneq ($(findstring Linux,$(shell uname -a)),) +else ifneq ($(findstring Darwin,$(shell uname -a)),) +else + ELF2RPL := $(ELF2RPL).exe +endif + + +INCDIRS := -I. -Ideps/zlib -Ideps/7zip -Ilibretro-common/include -Iwiiu -Iwiiu/include -I$(DEVKITPRO)/portlibs/ppc/include +LIBDIRS := -L. -L$(DEVKITPRO)/portlibs/ppc/lib + +CFLAGS := -mwup -mcpu=750 -meabi -mhard-float +LDFLAGS := + +ifeq ($(DEBUG), 1) + CFLAGS += -O0 -g +else + CFLAGS += -O3 +endif +LDFLAGS := $(CFLAGS) + +ASFLAGS := $(CFLAGS) -mregnames + +CFLAGS += -ffast-math -Werror=implicit-function-declaration +#CFLAGS += -fomit-frame-pointer -mword-relocations +#CFLAGS += -Wall + +#todo: remove -DWIIU and use the built-in macros instead (HW_WUP or __wiiu__). +CFLAGS += -DWIIU -DMSB_FIRST +CFLAGS += -DHAVE_MAIN +CFLAGS += -DRARCH_CONSOLE -DIS_SALAMANDER + +ifneq ($(PC_DEVELOPMENT_IP_ADDRESS),) + CFLAGS += -DPC_DEVELOPMENT_IP_ADDRESS='"$(PC_DEVELOPMENT_IP_ADDRESS)"' +endif + +ifneq ($(PC_DEVELOPMENT_TCP_PORT),) + CFLAGS += -DPC_DEVELOPMENT_TCP_PORT=$(PC_DEVELOPMENT_TCP_PORT) +endif + +ifeq ($(WHOLE_ARCHIVE_LINK), 1) + WHOLE_START := -Wl,--whole-archive + WHOLE_END := -Wl,--no-whole-archive +endif +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions + +LDFLAGS += -Wl,--gc-sections + +LIBS := $(WHOLE_START) -lretro_wiiu $(WHOLE_END) -lm -lfat -liosuhax + + +RPX_OBJ = wiiu/system/stubs_rpl.o +HBL_ELF_OBJ = wiiu/system/dynamic.o wiiu/system/stubs_elf.o + +RPX_LDFLAGS := -pie -fPIE +RPX_LDFLAGS += -z common-page-size=64 -z max-page-size=64 +RPX_LDFLAGS += -T wiiu/link_rpl.ld +RPX_LDFLAGS += -nostartfiles + +HBL_ELF_LDFLAGS := -T wiiu/link_elf.ld + +TARGETS := +ifeq ($(BUILD_RPX), 1) +TARGETS += $(TARGET).rpx +endif + +ifeq ($(BUILD_HBL_ELF), 1) +TARGETS += $(TARGET).elf +endif + +DEPFLAGS = -MT $@ -MMD -MP -MF $*.Tdepend +POSTCOMPILE = mv -f $*.Tdepend $*.depend + + +all: $(TARGETS) + +%.o: %.cpp +%.o: %.cpp %.depend + $(CXX) -c -o $@ $< $(CXXFLAGS) $(INCDIRS) $(DEPFLAGS) + $(POSTCOMPILE) + +%.o: %.c +%.o: %.c %.depend + $(CC) -c -o $@ $< $(CFLAGS) $(INCDIRS) $(DEPFLAGS) + $(POSTCOMPILE) + + +%.o: %.S +%.o: %.S %.depend + $(CC) -c -o $@ $< $(ASFLAGS) $(INCDIRS) $(DEPFLAGS) + $(POSTCOMPILE) + +%.o: %.s +%.o: %.s %.depend + $(CC) -c -o $@ $< $(ASFLAGS) $(INCDIRS) $(DEPFLAGS) + $(POSTCOMPILE) +%.a: + $(AR) -rc $@ $^ + +%.depend: ; + + +$(ELF2RPL): + $(MAKE) -C wiiu/wut/elf2rpl/ + +$(TARGET).elf: $(OBJ) $(HBL_ELF_OBJ) libretro_wiiu.a wiiu/link_elf.ld + $(LD) $(OBJ) $(HBL_ELF_OBJ) $(LDFLAGS) $(HBL_ELF_LDFLAGS) $(LIBDIRS) $(LIBS) -o $@ + +$(TARGET).rpx.elf: $(OBJ) $(RPX_OBJ) libretro_wiiu.a wiiu/link_elf.ld + $(LD) $(OBJ) $(RPX_OBJ) $(LDFLAGS) $(RPX_LDFLAGS) $(LIBDIRS) $(LIBS) -o $@ + +$(TARGET).rpx: $(TARGET).rpx.elf $(ELF2RPL) + -$(ELF2RPL) $(TARGET).rpx.elf $@ + +clean: + rm -f $(OBJ) $(RPX_OBJ) $(HBL_ELF_OBJ) $(TARGET).elf $(TARGET).rpx.elf $(TARGET).rpx + rm -f $(OBJ:.o=.depend) $(RPX_OBJ:.o=.depend) $(HBL_ELF_OBJ:.o=.depend) + +.PHONY: clean all +.PRECIOUS: %.depend + +-include $(OBJ:.o=.depend) $(RPX_OBJ:.o=.depend) $(HBL_ELF_OBJ:.o=.depend) + diff --git a/core_info.c b/core_info.c index b178441a5e..65aaea596b 100644 --- a/core_info.c +++ b/core_info.c @@ -198,7 +198,7 @@ static bool core_info_list_iterate( fill_pathname_base_noext(info_path_base, contents->elems[i].data, sizeof(info_path_base)); -#if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP) && !defined(_3DS) && !defined(VITA)) +#if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP) && !defined(_3DS) && !defined(VITA) && !defined(HW_WUP)) substr = strrchr(info_path_base, '_'); if (substr) *substr = '\0'; diff --git a/frontend/drivers/platform_wiiu.c b/frontend/drivers/platform_wiiu.c index 28b9aaff5d..6121164e8e 100644 --- a/frontend/drivers/platform_wiiu.c +++ b/frontend/drivers/platform_wiiu.c @@ -22,7 +22,9 @@ #include +#ifndef IS_SALAMANDER #include +#endif #include "../frontend_driver.h" #include "../frontend.h" @@ -56,17 +58,20 @@ #include #include "wiiu_dbg.h" +#include "hbl.h" +#ifndef IS_SALAMANDER #ifdef HAVE_MENU #include "../../menu/menu_driver.h" #endif +#endif //#define WIIU_SD_PATH "/vol/external01/" #define WIIU_SD_PATH "sd:/" #define WIIU_USB_PATH "usb:/" static enum frontend_fork wiiu_fork_mode = FRONTEND_FORK_NONE; -static const char* elf_path_cst = WIIU_SD_PATH "retroarch/retroarch.elf"; +static const char *elf_path_cst = WIIU_SD_PATH "retroarch/retroarch.elf"; static void frontend_wiiu_get_environment_settings(int *argc, char *argv[], void *args, void *params_data) @@ -139,7 +144,8 @@ enum frontend_architecture frontend_wiiu_get_architecture(void) static int frontend_wiiu_parse_drive_list(void *data) { - file_list_t *list = (file_list_t*)data; +#ifndef IS_SALAMANDER + file_list_t *list = (file_list_t *)data; if (!list) return -1; @@ -153,18 +159,125 @@ static int frontend_wiiu_parse_drive_list(void *data) msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR, MENU_SETTING_ACTION, 0, 0); - +#endif return 0; } -frontend_ctx_driver_t frontend_ctx_wiiu = { + +static void frontend_wiiu_exec(const char *path, bool should_load_game) +{ + + struct + { + u32 magic; + u32 argc; + char * argv[3]; + char args[]; + }*param = getApplicationEndAddr(); + int len = 0; + param->argc = 0; + + if(!path || !*path) + { + RARCH_LOG("No executable path provided, cannot Restart\n"); + } + + DEBUG_STR(path); + + strcpy(param->args + len, elf_path_cst); + param->argv[param->argc] = param->args + len; + len += strlen(param->args + len) + 1; + param->argc++; + + RARCH_LOG("Attempt to load core: [%s].\n", path); +#ifndef IS_SALAMANDER + if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) + { + strcpy(param->args + len, path_get(RARCH_PATH_CONTENT)); + param->argv[param->argc] = param->args + len; + len += strlen(param->args + len) + 1; + param->argc++; + + RARCH_LOG("content path: [%s].\n", path_get(RARCH_PATH_CONTENT)); + } +#endif + param->argv[param->argc] = NULL; + + { + if (HBL_loadToMemory(path, (u32)param->args - (u32)param + len) < 0) + RARCH_LOG("Failed to load core\n"); + else + { + param->magic = ARGV_MAGIC; + ARGV_PTR = param; + DEBUG_VAR(param->argc); + DEBUG_VAR(param->argv); + + } + } +} + +#ifndef IS_SALAMANDER +static bool frontend_wiiu_set_fork(enum frontend_fork fork_mode) +{ + switch (fork_mode) + { + case FRONTEND_FORK_CORE: + RARCH_LOG("FRONTEND_FORK_CORE\n"); + wiiu_fork_mode = fork_mode; + break; + case FRONTEND_FORK_CORE_WITH_ARGS: + RARCH_LOG("FRONTEND_FORK_CORE_WITH_ARGS\n"); + wiiu_fork_mode = fork_mode; + break; + case FRONTEND_FORK_RESTART: + RARCH_LOG("FRONTEND_FORK_RESTART\n"); + /* NOTE: We don't implement Salamander, so just turn + * this into FRONTEND_FORK_CORE. */ + wiiu_fork_mode = FRONTEND_FORK_CORE; + break; + case FRONTEND_FORK_NONE: + default: + return false; + } + + return true; +} +#endif + +static void frontend_wiiu_exitspawn(char *s, size_t len) +{ + bool should_load_game = false; +#ifndef IS_SALAMANDER + if (wiiu_fork_mode == FRONTEND_FORK_NONE) + return; + + switch (wiiu_fork_mode) + { + case FRONTEND_FORK_CORE_WITH_ARGS: + should_load_game = true; + break; + default: + break; + } +#endif + frontend_wiiu_exec(s, should_load_game); +} + + +frontend_ctx_driver_t frontend_ctx_wiiu = +{ frontend_wiiu_get_environment_settings, frontend_wiiu_init, frontend_wiiu_deinit, - NULL, /* exitspawn */ + frontend_wiiu_exitspawn, NULL, /* process_args */ - NULL, /* exec */ + frontend_wiiu_exec, +#ifdef IS_SALAMANDER NULL, /* set_fork */ +#else + frontend_wiiu_set_fork, +#endif frontend_wiiu_shutdown, NULL, /* get_name */ NULL, /* get_os */ @@ -187,68 +300,74 @@ frontend_ctx_driver_t frontend_ctx_wiiu = { static int log_socket = -1; static volatile int log_lock = 0; -void log_init(const char * ipString, int port) +void log_init(const char *ipString, int port) { - log_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (log_socket < 0) - return; + log_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - struct sockaddr_in connect_addr; - memset(&connect_addr, 0, sizeof(connect_addr)); - connect_addr.sin_family = AF_INET; - connect_addr.sin_port = port; - inet_aton(ipString, &connect_addr.sin_addr); + if (log_socket < 0) + return; - if(connect(log_socket, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) < 0) - { - socketclose(log_socket); - log_socket = -1; - } + struct sockaddr_in connect_addr; + memset(&connect_addr, 0, sizeof(connect_addr)); + connect_addr.sin_family = AF_INET; + connect_addr.sin_port = port; + inet_aton(ipString, &connect_addr.sin_addr); + + if (connect(log_socket, (struct sockaddr *)&connect_addr, sizeof(connect_addr)) < 0) + { + socketclose(log_socket); + log_socket = -1; + } } void log_deinit(void) { - if(log_socket >= 0) - { - socketclose(log_socket); - log_socket = -1; - } + if (log_socket >= 0) + { + socketclose(log_socket); + log_socket = -1; + } } -static ssize_t log_write(struct _reent *r, void* fd, const char *ptr, size_t len) +static ssize_t log_write(struct _reent *r, void *fd, const char *ptr, size_t len) { - if(log_socket < 0) - return len; + if (log_socket < 0) + return len; + + while (log_lock) + OSSleepTicks(((248625000 / 4)) / 1000); - while(log_lock) - OSSleepTicks(((248625000/4)) / 1000); log_lock = 1; int ret; - while (len > 0) { - int block = len < 1400 ? len : 1400; // take max 1400 bytes per UDP packet - ret = send(log_socket, ptr, block, 0); - if(ret < 0) - break; - len -= ret; - ptr += ret; + while (len > 0) + { + int block = len < 1400 ? len : 1400; // take max 1400 bytes per UDP packet + ret = send(log_socket, ptr, block, 0); + + if (ret < 0) + break; + + len -= ret; + ptr += ret; } log_lock = 0; return len; } -void net_print(const char* str) +void net_print(const char *str) { log_write(NULL, 0, str, strlen(str)); } -void net_print_exp(const char* str) +void net_print_exp(const char *str) { send(log_socket, str, strlen(str), 0); } -static devoptab_t dotab_stdout = { +static devoptab_t dotab_stdout = +{ "stdout_net", // device name 0, // size of file structure NULL, // device open @@ -264,13 +383,12 @@ void SaveCallback() } int main(int argc, char **argv) -{ +{ #if 1 setup_os_exceptions(); #else InstallExceptionHandler(); #endif - ProcUIInit(&SaveCallback); socket_lib_init(); @@ -279,22 +397,46 @@ int main(int argc, char **argv) devoptab_list[STD_OUT] = &dotab_stdout; devoptab_list[STD_ERR] = &dotab_stdout; #endif +#ifndef IS_SALAMANDER VPADInit(); WPADEnableURCC(true); WPADEnableWiiRemote(true); KPADInit(); - +#endif verbosity_enable(); + + printf("starting\n"); + fflush(stdout); + DEBUG_VAR(ARGV_PTR); + if(ARGV_PTR && ((u32)ARGV_PTR < 0x01000000)) + { + struct + { + u32 magic; + u32 argc; + char * argv[3]; + }*param = ARGV_PTR; + if(param->magic == ARGV_MAGIC) + { + argc = param->argc; + argv = param->argv; + } + ARGV_PTR = NULL; + } + DEBUG_VAR(argc); DEBUG_STR(argv[0]); DEBUG_STR(argv[1]); fflush(stdout); - +#ifdef IS_SALAMANDER + int salamander_main(int, char **); + salamander_main(argc, argv); +#else #if 1 #if 0 int argc_ = 2; // char* argv_[] = {WIIU_SD_PATH "retroarch/retroarch.elf", WIIU_SD_PATH "rom.nes", NULL}; - char* argv_[] = {WIIU_SD_PATH "retroarch/retroarch.elf", WIIU_SD_PATH "rom.sfc", NULL}; + char *argv_[] = {WIIU_SD_PATH "retroarch/retroarch.elf", WIIU_SD_PATH "rom.sfc", NULL}; rarch_main(argc_, argv_, NULL); #else @@ -306,14 +448,18 @@ int main(int argc, char **argv) int ret = runloop_iterate(&sleep_ms); if (ret == 1 && sleep_ms > 0) - retro_sleep(sleep_ms); - task_queue_ctl(TASK_QUEUE_CTL_WAIT, NULL); - if (ret == -1) - break; + retro_sleep(sleep_ms); - }while(1); + task_queue_ctl(TASK_QUEUE_CTL_WAIT, NULL); + + if (ret == -1) + break; + + } + while (1); main_exit(NULL); +#endif #endif fflush(stdout); fflush(stderr); @@ -322,6 +468,8 @@ int main(int argc, char **argv) #if defined(PC_DEVELOPMENT_IP_ADDRESS) && defined(PC_DEVELOPMENT_TCP_PORT) log_deinit(); #endif + + /* returning non 0 here can prevent loading a different rpx/elf in the HBL environment */ return 0; } @@ -340,7 +488,8 @@ void __init(void) { extern void(*__CTOR_LIST__[])(void); void(**ctor)(void) = __CTOR_LIST__; - while(*ctor) + + while (*ctor) (*ctor++)(); } @@ -350,7 +499,8 @@ void __fini(void) { extern void(*__DTOR_LIST__[])(void); void(**ctor)(void) = __DTOR_LIST__; - while(*ctor) + + while (*ctor) (*ctor++)(); } @@ -359,38 +509,80 @@ void __fini(void) //just to be able to call async void someFunc(void *arg) { - (void)arg; + (void)arg; } static int mcp_hook_fd = -1; + int MCPHookOpen() { - //take over mcp thread - mcp_hook_fd = IOS_Open("/dev/mcp", 0); - if(mcp_hook_fd < 0) - return -1; - IOS_IoctlAsync(mcp_hook_fd, 0x62, (void*)0, 0, (void*)0, 0, someFunc, (void*)0); - //let wupserver start up - retro_sleep(1000); - if(IOSUHAX_Open("/dev/mcp") < 0) - { - IOS_Close(mcp_hook_fd); - mcp_hook_fd = -1; - return -1; - } - return 0; + //take over mcp thread + mcp_hook_fd = IOS_Open("/dev/mcp", 0); + + if (mcp_hook_fd < 0) + return -1; + + IOS_IoctlAsync(mcp_hook_fd, 0x62, (void *)0, 0, (void *)0, 0, someFunc, (void *)0); + //let wupserver start up + retro_sleep(1000); + + if (IOSUHAX_Open("/dev/mcp") < 0) + { + IOS_Close(mcp_hook_fd); + mcp_hook_fd = -1; + return -1; + } + + return 0; } void MCPHookClose() { - if(mcp_hook_fd < 0) - return; - //close down wupserver, return control to mcp - IOSUHAX_Close(); - //wait for mcp to return - retro_sleep(1000); - IOS_Close(mcp_hook_fd); - mcp_hook_fd = -1; + if (mcp_hook_fd < 0) + return; + + //close down wupserver, return control to mcp + IOSUHAX_Close(); + //wait for mcp to return + retro_sleep(1000); + IOS_Close(mcp_hook_fd); + mcp_hook_fd = -1; +} + + +static int iosuhaxMount = 0; + +static void fsdev_init(void) +{ + iosuhaxMount = 0; + int res = IOSUHAX_Open(NULL); + + if (res < 0) + res = MCPHookOpen(); + + if (res < 0) + mount_sd_fat("sd"); + else + { + iosuhaxMount = 1; + fatInitDefault(); + } +} +static void fsdev_exit(void) +{ + if (iosuhaxMount) + { + fatUnmount("sd:"); + fatUnmount("usb:"); + + if (mcp_hook_fd >= 0) + MCPHookClose(); + else + IOSUHAX_Close(); + } + else + unmount_sd_fat("sd"); + } /* HBL elf entry point */ @@ -398,76 +590,29 @@ int __entry_menu(int argc, char **argv) { InitFunctionPointers(); memoryInitialize(); - - int iosuhaxMount = 0; - int res = IOSUHAX_Open(NULL); - if(res < 0) - res = MCPHookOpen(); - - if(res < 0) - mount_sd_fat("sd"); - else - { - iosuhaxMount = 1; - fatInitDefault(); - } - + fsdev_init(); __init(); + int ret = main(argc, argv); + __fini(); - - if(iosuhaxMount) - { - fatUnmount("sd:"); - fatUnmount("usb:"); - if(mcp_hook_fd >= 0) - MCPHookClose(); - else - IOSUHAX_Close(); - } - else - unmount_sd_fat("sd"); - + fsdev_exit(); memoryRelease(); return ret; } - /* RPX entry point */ __attribute__((noreturn)) void _start(int argc, char **argv) { memoryInitialize(); - - int iosuhaxMount = 0; - int res = IOSUHAX_Open(NULL); - if(res < 0) - res = MCPHookOpen(); - - if(res < 0) - mount_sd_fat("sd"); - else - { - iosuhaxMount = 1; - fatInitDefault(); - } - + fsdev_init(); __init(); + int ret = main(argc, argv); + __fini(); - - if(iosuhaxMount) - { - fatUnmount("sd:"); - fatUnmount("usb:"); - if(mcp_hook_fd >= 0) - MCPHookClose(); - else - IOSUHAX_Close(); - } - else - unmount_sd_fat("sd"); - + fsdev_exit(); memoryRelease(); - SYSRelaunchTitle(argc, argv); - exit(ret); + SYSRelaunchTitle(0, 0); + exit(0); } diff --git a/frontend/frontend_driver.c b/frontend/frontend_driver.c index d99005b887..d32480d71e 100644 --- a/frontend/frontend_driver.c +++ b/frontend/frontend_driver.c @@ -152,6 +152,9 @@ bool frontend_driver_get_core_extension(char *s, size_t len) #elif defined(GEKKO) strlcpy(s, "dol", len); return true; +#elif defined(HW_WUP) + strlcpy(s, "rpx|elf", len); + return true; #elif defined(__linux__) strlcpy(s, "elf", len); return true; diff --git a/frontend/frontend_salamander.c b/frontend/frontend_salamander.c index 5a9a13a20e..d07921f198 100644 --- a/frontend/frontend_salamander.c +++ b/frontend/frontend_salamander.c @@ -167,8 +167,11 @@ static void salamander_init(char *s, size_t len) } } } - +#ifdef HAVE_MAIN +int salamander_main(int argc, char *argv[]) +#else int main(int argc, char *argv[]) +#endif { char libretro_path[PATH_MAX_LENGTH] = {0}; void *args = NULL; diff --git a/wiiu/hbl.c b/wiiu/hbl.c new file mode 100644 index 0000000000..685cd42318 --- /dev/null +++ b/wiiu/hbl.c @@ -0,0 +1,256 @@ +/* adapted from https://github.com/dimok789/homebrew_launcher */ + +/**************************************************************************** + * + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#include +#include +#include +#include + +#include "hbl.h" + +#define MEM_AREA_TABLE ((s_mem_area*)(MEM_BASE + 0x1600)) +#define ELF_DATA_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x00)) +#define ELF_DATA_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x04)) +#define RPX_MAX_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x0C)) +#define RPX_MAX_CODE_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x10)) +#define APP_BASE_MEM ((unsigned char*)(MEM_BASE + 0x2000)) + +typedef struct _s_mem_area +{ + unsigned int address; + unsigned int size; + struct _s_mem_area *next; +} s_mem_area; + +void SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len); + +typedef struct _memory_values_t +{ + unsigned int start_address; + unsigned int end_address; +} memory_values_t; + +static const memory_values_t mem_vals_540[] = +{ + { 0x2E609EFC, 0x2FF82000 }, // 26083 kB + { 0x29030800, 0x293F6000 }, // 3864 kB + { 0x288EEC30, 0x28B06800 }, // 2144 kB + { 0x2D3B966C, 0x2D894000 }, // 4971 kB + { 0x2CB56370, 0x2D1EF000 }, // 6756 kB + { 0x2D8AD3D8, 0x2E000000 }, // 7499 kB + { 0x2970200C, 0x298B9800 }, // 1759 kB + { 0x2A057B68, 0x2A1B9000 }, // 1414 kB + { 0x2ABBCC4C, 0x2ACB9000 }, // 1010 kB + {0, 0} +}; + +static inline void memoryAddArea(int start, int end, int cur_index) +{ + // Create and copy new memory area + s_mem_area * mem_area = MEM_AREA_TABLE; + mem_area[cur_index].address = start; + mem_area[cur_index].size = end - start; + mem_area[cur_index].next = 0; + + // Fill pointer to this area in the previous area + if (cur_index > 0) + { + mem_area[cur_index - 1].next = &mem_area[cur_index]; + } +} +void *getApplicationEndAddr(void) +{ + extern u32 _end[]; + if((u32)_end >= 0x01000000) + return APP_BASE_MEM; + return _end; +} + +/* Create memory areas arrays */ +static void memoryInitAreaTable(u32 args_size) +{ + u32 ApplicationMemoryEnd = (u32)getApplicationEndAddr() + args_size; + + // This one seems to be available on every firmware and therefore its our code area but also our main RPX area behind our code + // 22876 kB - our application // ok + memoryAddArea(ApplicationMemoryEnd + 0x30000000, 0x30000000 + 0x01E20000, 0); + + const memory_values_t * mem_vals = mem_vals_540; + + // Fill entries + int i = 0; + while (mem_vals[i].start_address) + { + memoryAddArea(mem_vals[i].start_address, mem_vals[i].end_address, i + 1); + i++; + } +} + +static int HomebrewCopyMemory(u8 *address, u32 bytes, u32 args_size) +{ + args_size += 0x7; + args_size &= ~0x7; + if (args_size > 0x10000) + args_size = 0x10000; + + memoryInitAreaTable(args_size); + + RPX_MAX_SIZE = 0x40000000; + RPX_MAX_CODE_SIZE = 0x03000000; + + // check if we load an RPX or an ELF + if (*(u16 *)&address[7] != 0xCAFE) + { + // assume ELF + printf("loading ELF file \n"); + + ELF_DATA_ADDR = (u32)getApplicationEndAddr() + args_size; + if (ELF_DATA_ADDR >= 0x01000000) + return -1; + } + else + { + // RPX + printf("loading RPX file \n"); + + ELF_DATA_ADDR = MEM_AREA_TABLE->address; + } + + //! if we load an ELF file + if (ELF_DATA_ADDR < 0x01000000) + { + + if ((ELF_DATA_ADDR + bytes) > 0x01000000) + return -1; + + memcpy((void *)ELF_DATA_ADDR, address, bytes); + ELF_DATA_SIZE = bytes; + } + else + { + DCFlushRange(address, bytes); + + u32 done = 0; + u32 addressPhysical = (u32)OSEffectiveToPhysical(address); + + s_mem_area *mem_map = MEM_AREA_TABLE; + u32 mapPosition = 0; + + while ((done < bytes) && mem_map) + { + if (mapPosition >= mem_map->size) + { + mem_map = mem_map->next; + + if (!mem_map) + return -1; + + mapPosition = 0; + } + + u32 blockSize = bytes - done; + + if ((mapPosition + blockSize) > mem_map->size) + blockSize = mem_map->size - mapPosition; + + SC0x25_KernelCopyData(mem_map->address + mapPosition, (addressPhysical + done), blockSize); + + mapPosition += blockSize; + done += blockSize; + } + + ELF_DATA_SIZE = done; + } + return bytes; +} + +int HBL_loadToMemory(const char *filepath, u32 args_size) +{ + if (!filepath || !*filepath) + return -1; + + printf("Loading file %s\n", filepath); + + FILE *fp = fopen(filepath, "rb"); + + if (!fp) + { + printf("failed to open file %s\n", filepath); + return -1; + } + + u32 bytesRead = 0; + fseek(fp, 0, SEEK_END); + u32 fileSize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + + unsigned char *buffer = (unsigned char *) memalign(0x40, (fileSize + 0x3F) & ~0x3F); + + if (!buffer) + { + printf("Not enough memory\n"); + return -1; + } + + // Copy rpl in memory + while (bytesRead < fileSize) + { + printf("progress: %f \r", 100.0f * (f32)bytesRead / (f32)fileSize); + + u32 blockSize = 0x8000; + + if (blockSize > (fileSize - bytesRead)) + blockSize = fileSize - bytesRead; + + int ret = fread(buffer + bytesRead, 1, blockSize, fp); + + if (ret <= 0) + { + printf("Failure on reading file %s\n", filepath); + break; + } + + bytesRead += ret; + } + + printf("progress: %f \n", 100.0f * (f32)bytesRead / (f32)fileSize); + + if (bytesRead != fileSize) + { + free(buffer); + printf("File loading not finished for file %s, finished %i of %i bytes\n", filepath, bytesRead, + fileSize); + printf("File read failure"); + return -1; + } + + int ret = HomebrewCopyMemory(buffer, bytesRead, args_size); + + free(buffer); + + if (ret < 0) + { + printf("Not enough memory"); + return -1; + } + + return fileSize; +} diff --git a/wiiu/hbl.h b/wiiu/hbl.h new file mode 100644 index 0000000000..89cba6d735 --- /dev/null +++ b/wiiu/hbl.h @@ -0,0 +1,25 @@ +#ifndef __WIIU_HBL_LOADER_H__ +#define __WIIU_HBL_LOADER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MEM_BASE +#define MEM_BASE (0x00800000) +#endif + +#define ARGV_PTR (*(void* volatile *)(MEM_BASE + 0x1300 + 0x80)) + + +#define MAKE_MAGIC(c0, c1, c2, c3) (((c0) << 24) |((c1) << 16) |((c2) << 8) | c3) +#define ARGV_MAGIC MAKE_MAGIC('_', 'a', 'r', 'g') + +int HBL_loadToMemory(const char *filepath, u32 args_size); +void* getApplicationEndAddr(void); + +#ifdef __cplusplus +} +#endif + +#endif // __WIIU_HBL_LOADER_H__ diff --git a/wiiu/include/wiiu/fs.h b/wiiu/include/wiiu/fs.h index 77dca33247..0878f30f4f 100644 --- a/wiiu/include/wiiu/fs.h +++ b/wiiu/include/wiiu/fs.h @@ -160,9 +160,6 @@ typedef struct FSMountSource uint32_t __unknown[0xC0]; } FSMountSource; -FSStatus fsDevInit(); -FSStatus fsDevExit(); - void FSInit(); void FSShutdown(); diff --git a/wiiu/link_rpl.ld b/wiiu/link_rpl.ld index f2e0ac4e1d..2deb7293ff 100644 --- a/wiiu/link_rpl.ld +++ b/wiiu/link_rpl.ld @@ -170,6 +170,9 @@ SECTIONS { } : hdr_data __bss_end__ = .; + _end = .; + PROVIDE(end = .); + /* System stuff is for our elf2rpl converter to go through */ . = ORIGIN(system); diff --git a/wiiu/system/imports.h b/wiiu/system/imports.h index b6f6a9d8b1..a2dfe9be99 100644 --- a/wiiu/system/imports.h +++ b/wiiu/system/imports.h @@ -24,6 +24,7 @@ IMPORT(OSYieldThread); IMPORT(OSGetSystemTime); IMPORT(OSGetSystemTick); IMPORT(OSGetSymbolName); +IMPORT(OSEffectiveToPhysical); IMPORT(exit); IMPORT(_Exit); @@ -168,6 +169,7 @@ IMPORT_END(); IMPORT_BEGIN(sysapp); IMPORT(SYSRelaunchTitle); +IMPORT(SYSLaunchMenu); IMPORT_END(); diff --git a/wiiu/system/stubs_elf.S b/wiiu/system/stubs_elf.S index 2fb57eb6b1..6c6b40dd01 100644 --- a/wiiu/system/stubs_elf.S +++ b/wiiu/system/stubs_elf.S @@ -23,3 +23,9 @@ #include "imports.h" +.section ".text" +.globl SC0x25_KernelCopyData +SC0x25_KernelCopyData: +li r0, 0x2500 +sc +blr diff --git a/wiiu/system/stubs_rpl.S b/wiiu/system/stubs_rpl.S index 9dffaec458..6bd4ffdea9 100644 --- a/wiiu/system/stubs_rpl.S +++ b/wiiu/system/stubs_rpl.S @@ -51,3 +51,10 @@ .long 3b #include "imports.h" + +.section ".text" +.globl SC0x25_KernelCopyData +SC0x25_KernelCopyData: +li r0, 0x2500 +sc +blr