mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-27 02:00:41 +00:00
(WiiU) implement the missing requirement for core loading: exec,
exitspawn, set_fork and salamander.
This commit is contained in:
parent
0ba9faa8bd
commit
8f88d8fb4d
@ -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 :=
|
||||
|
||||
|
176
Makefile.wiiu.salamander
Normal file
176
Makefile.wiiu.salamander
Normal file
@ -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=<path to>devkitPPC")
|
||||
endif
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>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)
|
||||
|
@ -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';
|
||||
|
@ -22,7 +22,9 @@
|
||||
|
||||
#include <file/file_path.h>
|
||||
|
||||
#ifndef IS_SALAMANDER
|
||||
#include <lists/file_list.h>
|
||||
#endif
|
||||
|
||||
#include "../frontend_driver.h"
|
||||
#include "../frontend.h"
|
||||
@ -56,17 +58,20 @@
|
||||
#include <iosuhax.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
256
wiiu/hbl.c
Normal file
256
wiiu/hbl.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <wiiu/os.h>
|
||||
|
||||
#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;
|
||||
}
|
25
wiiu/hbl.h
Normal file
25
wiiu/hbl.h
Normal file
@ -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__
|
@ -160,9 +160,6 @@ typedef struct FSMountSource
|
||||
uint32_t __unknown[0xC0];
|
||||
} FSMountSource;
|
||||
|
||||
FSStatus fsDevInit();
|
||||
FSStatus fsDevExit();
|
||||
|
||||
void FSInit();
|
||||
void FSShutdown();
|
||||
|
||||
|
@ -170,6 +170,9 @@ SECTIONS {
|
||||
} : hdr_data
|
||||
__bss_end__ = .;
|
||||
|
||||
_end = .;
|
||||
PROVIDE(end = .);
|
||||
|
||||
/* System stuff is for our elf2rpl converter to go through */
|
||||
. = ORIGIN(system);
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -23,3 +23,9 @@
|
||||
|
||||
#include "imports.h"
|
||||
|
||||
.section ".text"
|
||||
.globl SC0x25_KernelCopyData
|
||||
SC0x25_KernelCopyData:
|
||||
li r0, 0x2500
|
||||
sc
|
||||
blr
|
||||
|
@ -51,3 +51,10 @@
|
||||
.long 3b
|
||||
|
||||
#include "imports.h"
|
||||
|
||||
.section ".text"
|
||||
.globl SC0x25_KernelCopyData
|
||||
SC0x25_KernelCopyData:
|
||||
li r0, 0x2500
|
||||
sc
|
||||
blr
|
||||
|
Loading…
Reference in New Issue
Block a user