diff --git a/Makefile.ctr b/Makefile.ctr index 0be7768b7e..c9a37f9b18 100644 --- a/Makefile.ctr +++ b/Makefile.ctr @@ -173,7 +173,7 @@ endif all: $(TARGET) -$(TARGET): $(TARGET_3DSX) $(TARGET_3DS) $(TARGET_CIA) +$(TARGET): $(TARGET_3DSX) $(TARGET_3DS) $(TARGET_CIA) $(TARGET).core $(TARGET).3dsx: $(TARGET).elf $(TARGET).elf: $(OBJ) libretro_ctr.a @@ -253,6 +253,9 @@ $(TARGET).3ds: $(TARGET).elf $(TARGET).bnr $(TARGET).icn $(APP_RSF) $(TARGET).cia: $(TARGET).elf $(TARGET).bnr $(TARGET).icn $(APP_RSF) $(MAKEROM) -f cia -o $@ $(MAKEROM_ARGS_COMMON) -DAPP_ENCRYPTED=false +$(TARGET).core: $(TARGET).elf + echo $(APP_UNIQUE_ID) > $(TARGET).core + clean: rm -f $(OBJ) @@ -260,6 +263,7 @@ clean: rm -f $(TARGET).elf rm -f $(TARGET).3ds rm -f $(TARGET).cia + rm -f $(TARGET).core rm -f $(TARGET).smdh rm -f $(TARGET).bnr rm -f $(TARGET).icn diff --git a/Makefile.ctr.salamander b/Makefile.ctr.salamander new file mode 100644 index 0000000000..769099a3af --- /dev/null +++ b/Makefile.ctr.salamander @@ -0,0 +1,203 @@ +TARGET := retroarch_3ds_salamander +LIBRETRO = + +DEBUG = 0 +BUILD_3DSX = 0 +BUILD_3DS = 0 +BUILD_CIA = 1 + +APP_TITLE = Retroarch 3DS +APP_DESCRIPTION = Retroarch 3DS +APP_AUTHOR = Team Libretro +APP_PRODUCT_CODE = RETROARCH-3DS +APP_UNIQUE_ID = 0xBAC00 +APP_ICON = ctr/assets/default.png +APP_BANNER = ctr/assets/libretro_banner.png +APP_AUDIO = ctr/assets/silent.wav +APP_RSF = ctr/tools/template.rsf +APP_SYSTEM_MODE = 64MB +APP_SYSTEM_MODE_EXT = 124MB + +OBJ := +OBJ += ctr/ctr_system.o +OBJ += ctr/ctr_memory.o +OBJ += ctr/ctr_linear.o +OBJ += frontend/frontend_salamander.o +OBJ += frontend/frontend_driver.o +OBJ += frontend/drivers/platform_ctr.o +OBJ += frontend/drivers/platform_null.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 $(DEVKITPRO)),) + $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitpro") +endif + +ifeq ($(strip $(CTRULIB)),) + CTRULIB = $(DEVKITPRO)/ctrulib +endif + +APP_TITLE := $(shell echo "$(APP_TITLE)" | cut -c1-128) +APP_DESCRIPTION := $(shell echo "$(APP_DESCRIPTION)" | cut -c1-256) +APP_AUTHOR := $(shell echo "$(APP_AUTHOR)" | cut -c1-128) +APP_PRODUCT_CODE := $(shell echo $(APP_PRODUCT_CODE) | cut -c1-16) +APP_UNIQUE_ID := $(shell echo $(APP_UNIQUE_ID) | cut -c1-7) + +MAKEROM_ARGS_COMMON = -rsf $(APP_RSF) -exefslogo -elf $(TARGET).elf -icon $(TARGET).icn -banner $(TARGET).bnr -DAPP_TITLE="$(APP_TITLE)" -DAPP_PRODUCT_CODE="$(APP_PRODUCT_CODE)" -DAPP_UNIQUE_ID=$(APP_UNIQUE_ID) -DAPP_SYSTEM_MODE=$(APP_SYSTEM_MODE) -DAPP_SYSTEM_MODE_EXT=$(APP_SYSTEM_MODE_EXT) + +INCDIRS := -I$(CTRULIB)/include +LIBDIRS := -L. -L$(CTRULIB)/lib + +ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -marm -mfpu=vfp -mtp=soft + +CFLAGS += -mword-relocations \ + -fomit-frame-pointer -ffast-math \ + -Werror=implicit-function-declaration \ + $(ARCH) + +#CFLAGS += -Wall +CFLAGS += -DARM11 -D_3DS + +ifeq ($(DEBUG), 1) + CFLAGS += -O0 -g +else + CFLAGS += -O3 +endif + +CFLAGS += -I. -Ideps/zlib -Ideps/7zip -Ilibretro-common/include + +#CFLAGS += -DRARCH_INTERNAL +CFLAGS += -DRARCH_CONSOLE -DIS_SALAMANDER + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) -O3 +LDFLAGS += -specs=ctr/3dsx_custom.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +CFLAGS += -std=gnu99 -ffast-math + + +LIBS := -lretro_ctr -lctru -lm + + +ifeq ($(BUILD_3DSX), 1) +TARGET_3DSX := $(TARGET).3dsx $(TARGET).smdh +endif + +ifeq ($(BUILD_3DS), 1) +TARGET_3DS := $(TARGET).3ds +endif + +ifeq ($(BUILD_CIA), 1) +TARGET_CIA := $(TARGET).cia +endif + +.PHONY: $(BUILD) clean all + +all: $(TARGET) + +$(TARGET): $(TARGET_3DSX) $(TARGET_3DS) $(TARGET_CIA) +$(TARGET).3dsx: $(TARGET).elf +$(TARGET).elf: $(OBJ) + +PREFIX := $(DEVKITPRO)/devkitARM/bin/arm-none-eabi- + +CC := $(PREFIX)gcc +CXX := $(PREFIX)g++ +AS := $(PREFIX)as +AR := $(PREFIX)ar +OBJCOPY := $(PREFIX)objcopy +STRIP := $(PREFIX)strip +NM := $(PREFIX)nm +LD := $(CXX) + +ifneq ($(findstring Linux,$(shell uname -a)),) + MAKEROM = ctr/tools/makerom-linux + BANNERTOOL = ctr/tools/bannertool-linux +else ifneq ($(findstring Darwin,$(shell uname -a)),) + MAKEROM = ctr/tools/makerom-mac + BANNERTOOL = ctr/tools/bannertool-mac +else + MAKEROM = ctr/tools/makerom.exe + BANNERTOOL = ctr/tools/bannertool.exe +endif + +%.o: %.vsh %.gsh + $(DEVKITPRO)/devkitARM/bin/picasso $^ -o $*.shbin + $(DEVKITPRO)/devkitARM/bin/bin2s $*.shbin | $(PREFIX)as -o $@ + rm $*.shbin + +%.o: %.vsh + $(DEVKITPRO)/devkitARM/bin/picasso $^ -o $*.shbin + $(DEVKITPRO)/devkitARM/bin/bin2s $*.shbin | $(PREFIX)as -o $@ + rm $*.shbin + +%.o: %.cpp + $(CXX) -c -o $@ $< $(CXXFLAGS) $(INCDIRS) + +%.o: %.c + $(CC) -c -o $@ $< $(CFLAGS) $(INCDIRS) + +%.o: %.s + $(CC) -c -o $@ $< $(ASFLAGS) + +%.o: %.S + $(CC) -c -o $@ $< $(ASFLAGS) + +%.a: + $(AR) -rc $@ $^ + +%.vsh: + +$(TARGET).smdh: $(APP_ICON) + smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@ + +$(TARGET).3dsx: $(TARGET).elf +ifeq ($(APP_BIG_TEXT_SECTION), 1) + cp ctr/big_text_section.xml $(TARGET).xml +else + rm -f $(TARGET).xml +endif + -3dsxtool $< $@ $(_3DSXFLAGS) + +$(TARGET).elf: ctr/3dsx_custom_crt0.o + $(LD) $(LDFLAGS) $(OBJ) $(LIBDIRS) $(LIBS) -o $@ + $(NM) -CSn $@ > $(notdir $*.lst) + +$(TARGET).bnr: $(APP_BANNER) $(APP_AUDIO) + $(BANNERTOOL) makebanner -i "$(APP_BANNER)" -a "$(APP_AUDIO)" -o $@ + +$(TARGET).icn: $(APP_ICON) + $(BANNERTOOL) makesmdh -s "$(APP_TITLE)" -l "$(APP_TITLE)" -p "$(APP_AUTHOR)" -i $(APP_ICON) -o $@ + +$(TARGET).3ds: $(TARGET).elf $(TARGET).bnr $(TARGET).icn $(APP_RSF) + $(MAKEROM) -f cci -o $@ $(MAKEROM_ARGS_COMMON) -DAPP_ENCRYPTED=true + +$(TARGET).cia: $(TARGET).elf $(TARGET).bnr $(TARGET).icn $(APP_RSF) + $(MAKEROM) -f cia -o $@ $(MAKEROM_ARGS_COMMON) -DAPP_ENCRYPTED=false + +clean: + rm -f $(OBJ) + rm -f $(TARGET).3dsx + rm -f $(TARGET).elf + rm -f $(TARGET).3ds + rm -f $(TARGET).cia + rm -f $(TARGET).smdh + rm -f $(TARGET).bnr + rm -f $(TARGET).icn + rm -f ctr/ctr_config_*.o + rm -f ctr/3dsx_custom_crt0.o + +.PHONY: clean + + diff --git a/core_info.c b/core_info.c index 050848ee55..31fad01098 100644 --- a/core_info.c +++ b/core_info.c @@ -171,7 +171,7 @@ static config_file_t *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)) +#if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP) && !defined(_3DS)) char *substr = strrchr(info_path_base, '_'); if (substr) *substr = '\0'; diff --git a/dist-scripts/dist-cores.sh b/dist-scripts/dist-cores.sh index ed3d5c9fae..76bf591aff 100755 --- a/dist-scripts/dist-cores.sh +++ b/dist-scripts/dist-cores.sh @@ -38,10 +38,12 @@ mkdir -p ../pkg/vita/vpk # CTR/3DS elif [ $PLATFORM = "ctr" ] ; then platform=ctr +SALAMANDER=yes EXT=a mkdir -p ../pkg/3ds/cia mkdir -p ../pkg/3ds/rom mkdir -p ../pkg/3ds/3ds +mkdir -p ../pkg/3ds/retroarch/cores # Emscripten elif [ $PLATFORM = "emscripten" ] ; then @@ -124,6 +126,10 @@ if [ $SALAMANDER = "yes" ]; then if [ $PLATFORM = "psp1" ] ; then mv -f ../EBOOT.PBP ../pkg/${platform}/EBOOT.PBP fi + if [ $PLATFORM = "ctr" ] ; then + mv -f ../retroarch_3ds_salamander.cia ../pkg/3ds/cia/retroarch_3ds.cia + make -C ../ -f Makefile.${platform} clean || exit 1 + fi if [ $PLATFORM = "wii" ] ; then mv -f ../retroarch-salamander_wii.dol ../pkg/${platform}/boot.dol fi @@ -243,6 +249,7 @@ for f in `ls -v *_${platform}.${EXT}`; do elif [ $PLATFORM = "ctr" ] ; then mv -f ../retroarch_3ds.cia ../pkg/3ds/cia/${name}_libretro.cia mv -f ../retroarch_3ds.3ds ../pkg/3ds/rom/${name}_libretro.3ds + mv -f ../retroarch_3ds.core ../pkg/3ds/retroarch/cores/${name}_libretro.core mkdir -p ../pkg/3ds/3ds/${name}_libretro mv -f ../retroarch_3ds.3dsx ../pkg/3ds/3ds/${name}_libretro/${name}_libretro.3dsx mv -f ../retroarch_3ds.smdh ../pkg/3ds/3ds/${name}_libretro/${name}_libretro.smdh diff --git a/frontend/drivers/platform_ctr.c b/frontend/drivers/platform_ctr.c index 88128fd7bf..fa58b55f51 100644 --- a/frontend/drivers/platform_ctr.c +++ b/frontend/drivers/platform_ctr.c @@ -35,6 +35,7 @@ #include "../../configuration.h" #include "../../verbosity.h" #include "../../defaults.h" +#include "../../paths.h" #include "retroarch.h" #include "file_path_special.h" #include "audio/audio_driver.h" @@ -47,7 +48,8 @@ #endif #endif -const char* elf_path_cst = "sdmc:/retroarch/test.3dsx"; +static enum frontend_fork ctr_fork_mode = FRONTEND_FORK_NONE; +static const char* elf_path_cst = "sdmc:/retroarch/test.3dsx"; static void frontend_ctr_get_environment_settings(int *argc, char *argv[], void *args, void *params_data) @@ -104,7 +106,8 @@ static void frontend_ctr_deinit(void *data) command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL); #endif - if(gfxBottomFramebuffers[0] == (u8*)currentConsole->frameBuffer) + if((gfxBottomFramebuffers[0] == (u8*)currentConsole->frameBuffer) + && (ctr_fork_mode == FRONTEND_FORK_NONE)) wait_for_input(); CFGU_GetModelNintendo2DS(¬_2DS); @@ -129,6 +132,118 @@ static void frontend_ctr_deinit(void *data) #endif } +static void frontend_ctr_exec(const char *path, bool should_load_game) +{ + struct + { + u32 argc; + char args[0x300 - 0x4]; + }param; + int len; + Result res; + extern char __argv_hmac[0x20]; + + DEBUG_VAR(path); + DEBUG_STR(path); + + strlcpy(param.args, elf_path_cst, sizeof(param.args)); + len = strlen(param.args) + 1; + param.argc = 1; + + RARCH_LOG("Attempt to load core: [%s].\n", path); +#ifndef IS_SALAMANDER + if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) + { + strlcpy(param.args + len, path_get(RARCH_PATH_CONTENT), sizeof(param.args) - len); + len += strlen(param.args + len) + 1; + param.argc++; + RARCH_LOG("content path: [%s].\n", path_get(RARCH_PATH_CONTENT)); + } +#endif + uint64_t app_ID; + if(!path || !*path) + { + APT_GetProgramID(&app_ID); + RARCH_LOG("APP_ID 0x%016llX.\n", app_ID); + } + else + { + u32 app_ID_low; + char app_ID_str[11]; + FILE* fp = fopen(path, "rb"); + size_t bytes_read = fread(app_ID_str, 1, sizeof(app_ID_str), fp); + fclose(fp); + if(bytes_read <= 0) + { + RARCH_LOG("error reading APP_ID from: [%s].\n", path); + return; + } + app_ID_str[bytes_read] = '\0'; + sscanf(app_ID_str, "0x%x", &app_ID_low); + app_ID_low <<= 8; + app_ID = 0x0004000000000000ULL | app_ID_low; + RARCH_LOG("APP_ID [%s] -- > 0x%016llX.\n", app_ID_str, app_ID); + } + + if(R_SUCCEEDED(res = APT_PrepareToDoApplicationJump(0, app_ID, 0x1))) + res = APT_DoApplicationJump(¶m, sizeof(param.argc) + len, __argv_hmac); + + if(res) + { + RARCH_LOG("Failed to load core\n"); + dump_result_value(res); + } + + svcSleepThread(INT64_MAX); +} + +#ifndef IS_SALAMANDER +static bool frontend_ctr_set_fork(enum frontend_fork fork_mode) +{ + switch (fork_mode) + { + case FRONTEND_FORK_CORE: + RARCH_LOG("FRONTEND_FORK_CORE\n"); + ctr_fork_mode = fork_mode; + break; + case FRONTEND_FORK_CORE_WITH_ARGS: + RARCH_LOG("FRONTEND_FORK_CORE_WITH_ARGS\n"); + ctr_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. */ + ctr_fork_mode = FRONTEND_FORK_CORE; + break; + case FRONTEND_FORK_NONE: + default: + return false; + } + + return true; +} +#endif + +static void frontend_ctr_exitspawn(char *s, size_t len) +{ + bool should_load_game = false; +#ifndef IS_SALAMANDER + if (ctr_fork_mode == FRONTEND_FORK_NONE) + return; + + switch (ctr_fork_mode) + { + case FRONTEND_FORK_CORE_WITH_ARGS: + should_load_game = true; + break; + default: + break; + } +#endif + frontend_ctr_exec(s, should_load_game); +} + static void frontend_ctr_shutdown(bool unused) { (void)unused; @@ -192,6 +307,15 @@ static void frontend_ctr_init(void *data) { #ifndef IS_SALAMANDER (void)data; + + extern void* __service_ptr; + if (__service_ptr) + { + frontend_ctx_ctr.exec = NULL; + frontend_ctx_ctr.exitspawn = NULL; + frontend_ctx_ctr.set_fork = NULL; + } + verbosity_enable(); gfxInit(GSP_BGR8_OES,GSP_RGB565_OES,false); @@ -255,9 +379,9 @@ enum frontend_architecture frontend_ctr_get_architecture(void) static int frontend_ctr_parse_drive_list(void *data) { +#ifndef IS_SALAMANDER file_list_t *list = (file_list_t*)data; -#ifndef IS_SALAMANDER if (!list) return -1; @@ -272,10 +396,14 @@ frontend_ctx_driver_t frontend_ctx_ctr = { frontend_ctr_get_environment_settings, frontend_ctr_init, frontend_ctr_deinit, - NULL, /* exitspawn */ + frontend_ctr_exitspawn, NULL, /* process_args */ - NULL, /* exec */ - NULL, /* set_fork */ + frontend_ctr_exec, +#ifdef IS_SALAMANDER + NULL, +#else + frontend_ctr_set_fork, +#endif frontend_ctr_shutdown, NULL, /* get_name */ NULL, /* get_os */ diff --git a/frontend/frontend_driver.c b/frontend/frontend_driver.c index 1e6c6073f3..52143a664e 100644 --- a/frontend/frontend_driver.c +++ b/frontend/frontend_driver.c @@ -149,6 +149,9 @@ bool frontend_driver_get_core_extension(char *s, size_t len) #elif defined(__linux__) strlcpy(s, "elf", len); return true; +#elif defined(_3DS) + strlcpy(s, "core", len); + return true; #else return false; #endif @@ -180,6 +183,9 @@ bool frontend_driver_get_salamander_basename(char *s, size_t len) #elif defined(HW_RVL) strlcpy(s, "boot.dol", len); return true; +#elif defined(_3DS) + strlcpy(s, "retroarch.core", len); + return true; #else return false; #endif