diff --git a/Makefile.ps3 b/Makefile.ps3 index 1a87c0db07..9331c1137f 100644 --- a/Makefile.ps3 +++ b/Makefile.ps3 @@ -34,6 +34,7 @@ endif STRIP = $(CELL_SDK)/$(HOST_DIR)/ppu/bin/ppu-lv2-strip PPU_TARGET := ssnes.elf +SALAMANDER_TARGET := ssnes-salamander.elf LDDIRS = -L. -L$(CELL_SDK)/target/ppu/lib/PSGL/RSX/ultra-opt INCDIRS = -I. -Icommon @@ -43,6 +44,8 @@ MAKE_PACKAGE_NPDRM = $(CELL_HOST_PATH)/bin/make_package_npdrm OBJ = fifo_buffer.o ps3/cellframework2/fileio/file_browser.o ps3/ps3_audio.o ps3/menu.o console/main_wrap.o console/rom_ext.o ps3/ps3_input.o ps3/cellframework2/input/pad_input.o getopt.o ssnes.o driver.o file.o settings.o message.o rewind.o movie.o netplay.o netplay_compat.o gfx/gfx_common.o ps3/ps3_video_psgl.o gfx/shader_cg.o gfx/snes_state.o ups.o bps.o strl.o audio/hermite.o dynamic.o ps3/main.o audio/utils.o conf/config_file.o ps3/image.o +SALAMANDER_CSRCS = ps3/salamander/main.c conf/config_file.c strl.c + ifeq ($(HAVE_SSNES_GL), 1) DEFINES = -DHAVE_SSNES_GL GL_LIBS := -lSSNESGL -lSSNESGLcgc @@ -60,8 +63,6 @@ else PPU_OPTIMIZE_LV := -O3 -g endif - -## Use this for new SDK! CFLAGS = $(PPU_OPTIMIZE_LV) $(DEFINES) CXXFLAGS = $(PPU_OPTIMIZE_LV) $(DEFINES) @@ -81,14 +82,16 @@ endif pkg: $(PPU_TARGET) ifeq ($(DOWNLOAD_SHADERS),1) - rm -rf ps3/pkg/USRDIR/shaders - git clone git://github.com/twinaphex/common-shaders.git ps3/pkg/USRDIR/shaders + rm -rf ps3/pkg/USRDIR/cores/shaders + git clone git://github.com/twinaphex/common-shaders.git ps3/pkg/USRDIR/cores/shaders endif - $(MAKE_FSELF_NPDRM) $(PPU_TARGET) ps3/pkg/USRDIR/EBOOT.BIN - $(MAKE_FSELF_NPDRM) $(PPU_TARGET) ps3/pkg/USRDIR/CORE.SELF + $(MAKE_FSELF_NPDRM) $(PPU_TARGET) ps3/pkg/USRDIR/cores/CORE.SELF + $(CC) -g -L. -ldbgfont -lgcm_cmd -lgcm_sys_stub -lm -lio_stub -lfs_stub -lsysutil_stub -lsysutil_game_stub -lsysutil_np_stub -lsysmodule_stub -lnet_stub $(SALAMANDER_CSRCS) -o $(SALAMANDER_TARGET) + $(MAKE_FSELF_NPDRM) $(SALAMANDER_TARGET) ps3/pkg/USRDIR/EBOOT.BIN $(MAKE_PACKAGE_NPDRM) ps3/pkg/package.conf ps3/pkg clean: + rm -f $(SALAMANDER_TARGET) rm -f $(PPU_TARGET) rm -f $(OBJ) rm -f *.pkg diff --git a/ps3/main.c b/ps3/main.c index a1ef239483..3f48087f98 100644 --- a/ps3/main.c +++ b/ps3/main.c @@ -64,9 +64,11 @@ char PRESETS_DIR_PATH[MAX_PATH_LENGTH]; char INPUT_PRESETS_DIR_PATH[MAX_PATH_LENGTH]; char BORDERS_DIR_PATH[MAX_PATH_LENGTH]; char SHADERS_DIR_PATH[MAX_PATH_LENGTH]; +char LIBSNES_DIR_PATH[MAX_PATH_LENGTH]; char DEFAULT_SHADER_FILE[MAX_PATH_LENGTH]; char DEFAULT_MENU_SHADER_FILE[MAX_PATH_LENGTH]; char SYS_CONFIG_FILE[MAX_PATH_LENGTH]; +char EMULATOR_CORE_SELF[MAX_PATH_LENGTH]; const char * MULTIMAN_EXECUTABLE = "/dev_hdd0/game/BLES80608/USRDIR/RELOAD.SELF"; @@ -165,7 +167,7 @@ static void set_default_settings(void) g_extern.verbose = true; } -static void init_settings(void) +static void init_settings(bool load_libsnes_path) { if(!path_file_exists(SYS_CONFIG_FILE)) { @@ -174,90 +176,129 @@ static void init_settings(void) f = fopen(SYS_CONFIG_FILE, "w"); fclose(f); } + else + { - config_file_t * conf = config_file_new(SYS_CONFIG_FILE); + config_file_t * conf = config_file_new(SYS_CONFIG_FILE); - // g_settings + // g_settings - CONFIG_GET_STRING(cheat_database, "cheat_database"); - CONFIG_GET_BOOL(rewind_enable, "rewind_enable"); - CONFIG_GET_STRING(video.cg_shader_path, "video_cg_shader"); - CONFIG_GET_STRING(video.second_pass_shader, "video_second_pass_shader"); - CONFIG_GET_FLOAT(video.fbo_scale_x, "video_fbo_scale_x"); - CONFIG_GET_FLOAT(video.fbo_scale_y, "video_fbo_scale_y"); - CONFIG_GET_BOOL(video.render_to_texture, "video_render_to_texture"); - CONFIG_GET_BOOL(video.second_pass_smooth, "video_second_pass_smooth"); - CONFIG_GET_BOOL(video.smooth, "video_smooth"); - CONFIG_GET_BOOL(video.vsync, "video_vsync"); - CONFIG_GET_FLOAT(video.aspect_ratio, "video_aspect_ratio"); + if(load_libsnes_path) + { + CONFIG_GET_STRING(libsnes, "libsnes_path"); - // g_console + if(!strcmp(g_settings.libsnes, "")) + { + //We need to set libsnes to the first entry in the cores + //directory so that it will be saved to the config file + char ** dir_list = dir_list_new(LIBSNES_DIR_PATH, ".SELF"); + if (!dir_list) + { + SSNES_ERR("Couldn't read cores directory.\n"); + return; + } - CONFIG_GET_BOOL_CONSOLE(overscan_enable, "overscan_enable"); - CONFIG_GET_BOOL_CONSOLE(screenshots_enable, "screenshots_enable"); - CONFIG_GET_BOOL_CONSOLE(throttle_enable, "throttle_enable"); - CONFIG_GET_BOOL_CONSOLE(triple_buffering_enable, "triple_buffering_enable"); - CONFIG_GET_INT_CONSOLE(aspect_ratio_index, "aspect_ratio_index"); - CONFIG_GET_INT_CONSOLE(current_resolution_id, "current_resolution_id"); - CONFIG_GET_INT_CONSOLE(screen_orientation, "screen_orientation"); - CONFIG_GET_STRING_CONSOLE(aspect_ratio_name, "aspect_ratio_name"); - CONFIG_GET_STRING_CONSOLE(default_rom_startup_dir, "default_rom_startup_dir"); - CONFIG_GET_FLOAT_CONSOLE(menu_font_size, "menu_font_size"); - CONFIG_GET_FLOAT_CONSOLE(overscan_amount, "overscan_amount"); - - // g_extern - CONFIG_GET_INT_EXTERN(state_slot, "state_slot"); - CONFIG_GET_INT_EXTERN(audio_data.mute, "audio_mute"); + const char * first_self = dir_list[0]; + + if(first_self) + { + SSNES_LOG("Set first entry in libsnes cores dir: [%s] to libsnes path.\n", first_self); + strlcpy(g_settings.libsnes, first_self, sizeof(g_settings.libsnes)); + } + else + { + SSNES_ERR("Failed to set first entry in libsnes cores dir to libsnes path.\n"); + } + + dir_list_free(dir_list); + } + } + + CONFIG_GET_STRING(cheat_database, "cheat_database"); + CONFIG_GET_BOOL(rewind_enable, "rewind_enable"); + CONFIG_GET_STRING(video.cg_shader_path, "video_cg_shader"); + CONFIG_GET_STRING(video.second_pass_shader, "video_second_pass_shader"); + CONFIG_GET_FLOAT(video.fbo_scale_x, "video_fbo_scale_x"); + CONFIG_GET_FLOAT(video.fbo_scale_y, "video_fbo_scale_y"); + CONFIG_GET_BOOL(video.render_to_texture, "video_render_to_texture"); + CONFIG_GET_BOOL(video.second_pass_smooth, "video_second_pass_smooth"); + CONFIG_GET_BOOL(video.smooth, "video_smooth"); + CONFIG_GET_BOOL(video.vsync, "video_vsync"); + CONFIG_GET_FLOAT(video.aspect_ratio, "video_aspect_ratio"); + + // g_console + + CONFIG_GET_BOOL_CONSOLE(overscan_enable, "overscan_enable"); + CONFIG_GET_BOOL_CONSOLE(screenshots_enable, "screenshots_enable"); + CONFIG_GET_BOOL_CONSOLE(throttle_enable, "throttle_enable"); + CONFIG_GET_BOOL_CONSOLE(triple_buffering_enable, "triple_buffering_enable"); + CONFIG_GET_INT_CONSOLE(aspect_ratio_index, "aspect_ratio_index"); + CONFIG_GET_INT_CONSOLE(current_resolution_id, "current_resolution_id"); + CONFIG_GET_INT_CONSOLE(screen_orientation, "screen_orientation"); + CONFIG_GET_STRING_CONSOLE(aspect_ratio_name, "aspect_ratio_name"); + CONFIG_GET_STRING_CONSOLE(default_rom_startup_dir, "default_rom_startup_dir"); + CONFIG_GET_FLOAT_CONSOLE(menu_font_size, "menu_font_size"); + CONFIG_GET_FLOAT_CONSOLE(overscan_amount, "overscan_amount"); + + // g_extern + CONFIG_GET_INT_EXTERN(state_slot, "state_slot"); + CONFIG_GET_INT_EXTERN(audio_data.mute, "audio_mute"); + } } static void save_settings(void) { if(!path_file_exists(SYS_CONFIG_FILE)) { + SSNES_ERR("Config file \"%s\" doesn't exist. Creating...\n", SYS_CONFIG_FILE); FILE * f; f = fopen(SYS_CONFIG_FILE, "w"); fclose(f); } + else + { - config_file_t * conf = config_file_new(SYS_CONFIG_FILE); + config_file_t * conf = config_file_new(SYS_CONFIG_FILE); - if(conf == NULL) - conf = config_file_new(NULL); + if(conf == NULL) + conf = config_file_new(NULL); - // g_settings - config_set_string(conf, "cheat_database_path", g_settings.cheat_database); - config_set_bool(conf, "rewind_enable", g_settings.rewind_enable); - config_set_string(conf, "video_cg_shader", g_settings.video.cg_shader_path); - config_set_string(conf, "video_second_pass_shader", g_settings.video.second_pass_shader); - config_set_float(conf, "video_aspect_ratio", g_settings.video.aspect_ratio); - config_set_float(conf, "video_fbo_scale_x", g_settings.video.fbo_scale_x); - config_set_float(conf, "video_fbo_scale_y", g_settings.video.fbo_scale_y); - config_set_bool(conf, "video_render_to_texture", g_settings.video.render_to_texture); - config_set_bool(conf, "video_second_pass_smooth", g_settings.video.second_pass_smooth); - config_set_bool(conf, "video_smooth", g_settings.video.smooth); - config_set_bool(conf, "video_vsync", g_settings.video.vsync); + // g_settings + config_set_string(conf, "libsnes_path", g_settings.libsnes); + config_set_string(conf, "cheat_database_path", g_settings.cheat_database); + config_set_bool(conf, "rewind_enable", g_settings.rewind_enable); + config_set_string(conf, "video_cg_shader", g_settings.video.cg_shader_path); + config_set_string(conf, "video_second_pass_shader", g_settings.video.second_pass_shader); + config_set_float(conf, "video_aspect_ratio", g_settings.video.aspect_ratio); + config_set_float(conf, "video_fbo_scale_x", g_settings.video.fbo_scale_x); + config_set_float(conf, "video_fbo_scale_y", g_settings.video.fbo_scale_y); + config_set_bool(conf, "video_render_to_texture", g_settings.video.render_to_texture); + config_set_bool(conf, "video_second_pass_smooth", g_settings.video.second_pass_smooth); + config_set_bool(conf, "video_smooth", g_settings.video.smooth); + config_set_bool(conf, "video_vsync", g_settings.video.vsync); - // g_console - config_set_bool(conf, "overscan_enable", g_console.overscan_enable); - config_set_bool(conf, "screenshots_enable", g_console.screenshots_enable); - config_set_bool(conf, "throttle_enable", g_console.throttle_enable); - config_set_bool(conf, "triple_buffering_enable", g_console.triple_buffering_enable); - config_set_int(conf, "aspect_ratio_index", g_console.aspect_ratio_index); - config_set_int(conf, "current_resolution_id", g_console.current_resolution_id); - config_set_int(conf, "screen_orientation", g_console.screen_orientation); - config_set_string(conf, "aspect_ratio_name", g_console.aspect_ratio_name); - config_set_string(conf, "default_rom_startup_dir", g_console.default_rom_startup_dir); - config_set_float(conf, "menu_font_size", g_console.menu_font_size); - config_set_float(conf, "overscan_amount", g_console.overscan_amount); + // g_console + config_set_bool(conf, "overscan_enable", g_console.overscan_enable); + config_set_bool(conf, "screenshots_enable", g_console.screenshots_enable); + config_set_bool(conf, "throttle_enable", g_console.throttle_enable); + config_set_bool(conf, "triple_buffering_enable", g_console.triple_buffering_enable); + config_set_int(conf, "aspect_ratio_index", g_console.aspect_ratio_index); + config_set_int(conf, "current_resolution_id", g_console.current_resolution_id); + config_set_int(conf, "screen_orientation", g_console.screen_orientation); + config_set_string(conf, "aspect_ratio_name", g_console.aspect_ratio_name); + config_set_string(conf, "default_rom_startup_dir", g_console.default_rom_startup_dir); + config_set_float(conf, "menu_font_size", g_console.menu_font_size); + config_set_float(conf, "overscan_amount", g_console.overscan_amount); - // g_extern - config_set_int(conf, "state_slot", g_extern.state_slot); - config_set_int(conf, "audio_mute", g_extern.audio_data.mute); + // g_extern + config_set_int(conf, "state_slot", g_extern.state_slot); + config_set_int(conf, "audio_mute", g_extern.audio_data.mute); - if (!config_file_write(conf, SYS_CONFIG_FILE)) - SSNES_ERR("Failed to write config file to \"%s\". Check permissions.\n", SYS_CONFIG_FILE); + if (!config_file_write(conf, SYS_CONFIG_FILE)) + SSNES_ERR("Failed to write config file to \"%s\". Check permissions.\n", SYS_CONFIG_FILE); - free(conf); + free(conf); + } } static void callback_sysutil_exit(uint64_t status, uint64_t param, void *userdata) @@ -285,8 +326,6 @@ static void get_environment_settings(int argc) CellGameContentSize size; char dirName[CELL_GAME_DIRNAME_SIZE]; - SSNES_LOG("Registering system utility callback...\n"); - cellSysutilRegisterCallback(0, callback_sysutil_exit, NULL); if(path_file_exists(MULTIMAN_EXECUTABLE)) { @@ -299,6 +338,7 @@ static void get_environment_settings(int argc) SSNES_WARN("multiMAN not found, support disabled.\n"); } + #if 0 if(argc > 1) { g_console.autostart_game = true; @@ -306,6 +346,7 @@ static void get_environment_settings(int argc) } else g_console.autostart_game = false; + #endif memset(&size, 0x00, sizeof(CellGameContentSize)); @@ -353,15 +394,16 @@ static void get_environment_settings(int argc) } /* now we fill in all the variables */ - snprintf(DEFAULT_PRESET_FILE, sizeof(DEFAULT_PRESET_FILE), "%s/presets/stock.conf", usrDirPath); - snprintf(DEFAULT_BORDER_FILE, sizeof(DEFAULT_BORDER_FILE), "%s/borders/Centered-1080p/mega-man-2.png", usrDirPath); - snprintf(DEFAULT_MENU_BORDER_FILE, sizeof(DEFAULT_MENU_BORDER_FILE), "%s/borders/Menu/main-menu.png", usrDirPath); - snprintf(PRESETS_DIR_PATH, sizeof(PRESETS_DIR_PATH), "%s/presets", usrDirPath); - snprintf(INPUT_PRESETS_DIR_PATH, sizeof(INPUT_PRESETS_DIR_PATH), "%s/input-presets", usrDirPath); - snprintf(BORDERS_DIR_PATH, sizeof(BORDERS_DIR_PATH), "%s/borders", usrDirPath); - snprintf(SHADERS_DIR_PATH, sizeof(SHADERS_DIR_PATH), "%s/shaders", usrDirPath); - snprintf(DEFAULT_SHADER_FILE, sizeof(DEFAULT_SHADER_FILE), "%s/shaders/stock.cg", usrDirPath); - snprintf(DEFAULT_MENU_SHADER_FILE, sizeof(DEFAULT_MENU_SHADER_FILE), "%s/shaders/Borders/Menu/border-only-ssnes.cg", usrDirPath); + snprintf(DEFAULT_PRESET_FILE, sizeof(DEFAULT_PRESET_FILE), "%s/cores/presets/stock.conf", usrDirPath); + snprintf(DEFAULT_BORDER_FILE, sizeof(DEFAULT_BORDER_FILE), "%s/cores/borders/Centered-1080p/mega-man-2.png", usrDirPath); + snprintf(DEFAULT_MENU_BORDER_FILE, sizeof(DEFAULT_MENU_BORDER_FILE), "%s/cores/borders/Menu/main-menu.png", usrDirPath); + snprintf(PRESETS_DIR_PATH, sizeof(PRESETS_DIR_PATH), "%s/cores/presets", usrDirPath); + snprintf(INPUT_PRESETS_DIR_PATH, sizeof(INPUT_PRESETS_DIR_PATH), "%s/cores/input-presets", usrDirPath); + snprintf(LIBSNES_DIR_PATH, sizeof(LIBSNES_DIR_PATH), "%s/cores", usrDirPath); + snprintf(BORDERS_DIR_PATH, sizeof(BORDERS_DIR_PATH), "%s/cores/borders", usrDirPath); + snprintf(SHADERS_DIR_PATH, sizeof(SHADERS_DIR_PATH), "%s/cores/shaders", usrDirPath); + snprintf(DEFAULT_SHADER_FILE, sizeof(DEFAULT_SHADER_FILE), "%s/cores/shaders/stock.cg", usrDirPath); + snprintf(DEFAULT_MENU_SHADER_FILE, sizeof(DEFAULT_MENU_SHADER_FILE), "%s/cores/shaders/Borders/Menu/border-only-ssnes.cg", usrDirPath); snprintf(SYS_CONFIG_FILE, sizeof(SYS_CONFIG_FILE), "%s/ssnes.cfg", usrDirPath); } @@ -389,8 +431,85 @@ static void startup_ssnes(void) } } +static bool manage_libsnes_core(void) +{ + g_extern.verbose = true; + bool return_code; + + bool set_libsnes_path = false; + char tmp_path[1024], tmp_path2[1024], tmp_pathnewfile[1024]; + snprintf(tmp_path, sizeof(tmp_path), "%s/cores/CORE.SELF", usrDirPath); + SSNES_LOG("Assumed path of CORE.SELF: [%s]\n", tmp_path); + if(path_file_exists(tmp_path)) + { + //if CORE.SELF exists, this indicates we have just installed + //a new libsnes port and that we need to change it to a more + //sane name. + + CellFsErrno ret; + + ssnes_console_name_from_id(tmp_path2, sizeof(tmp_path2)); + strlcat(tmp_path2, ".SELF", sizeof(tmp_path2)); + snprintf(tmp_pathnewfile, sizeof(tmp_pathnewfile), "%s/cores/%s", usrDirPath, tmp_path2); + + if(path_file_exists(tmp_pathnewfile)) + { + SSNES_LOG("Upgrading emulator core...\n"); + //if libsnes core already exists, then that means we are + //upgrading the libsnes core - so delete pre-existing + //file first + ret = cellFsUnlink(tmp_pathnewfile); + if(ret == CELL_FS_SUCCEEDED) + { + SSNES_LOG("Succeeded in removing pre-existing libsnes core: [%s].\n", tmp_pathnewfile); + } + else + { + SSNES_LOG("Failed to remove pre-existing libsnes core: [%s].\n", tmp_pathnewfile); + } + } + + //now attempt the renaming + ret = cellFsRename(tmp_path, tmp_pathnewfile); + if(ret != CELL_FS_SUCCEEDED) + { + SSNES_ERR("Failed to rename CORE.SELF.\n"); + } + else + { + SSNES_LOG("Libsnes core [%s] renamed to: [%s].\n", tmp_path, tmp_pathnewfile); + set_libsnes_path = true; + } + } + else + { + SSNES_LOG("CORE.SELF was not found, libsnes core path will be loaded from config file.\n"); + } + + if(set_libsnes_path) + { + //CORE.BIN has been renamed, libsnes path will now be set to the recently + //renamed new libsnes core + strlcpy(g_settings.libsnes, tmp_pathnewfile, sizeof(g_settings.libsnes)); + return_code = 0; + } + else + { + //There was no CORE.BIN present, or the CORE.BIN file was not renamed. + //The libsnes core path will still be loaded from the config file + return_code = 1; + } + + g_extern.verbose = false; + + return return_code; +} + int main(int argc, char *argv[]) { + SSNES_LOG("Registering system utility callback...\n"); + cellSysutilRegisterCallback(0, callback_sysutil_exit, NULL); + cellSysmoduleLoadModule(CELL_SYSMODULE_IO); cellSysmoduleLoadModule(CELL_SYSMODULE_FS); cellSysmoduleLoadModule(CELL_SYSMODULE_SYSUTIL_GAME); @@ -410,8 +529,10 @@ int main(int argc, char *argv[]) config_set_defaults(); + bool load_libsnes_path = manage_libsnes_core(); + set_default_settings(); - init_settings(); + init_settings(load_libsnes_path); #if(CELL_SDK_VERSION > 0x340000) if (g_console.screenshots_enable) @@ -483,8 +604,6 @@ begin_shutdown: sys_game_process_exitspawn2((char*)MULTIMAN_EXECUTABLE, NULL, NULL, NULL, 0, 2048, SYS_PROCESS_PRIMARY_STACK_SIZE_1M); */ - char self_path[1024]; - snprintf(self_path, sizeof(self_path), "%s/CORE.SELF", usrDirPath); char spawn_data[256]; for(unsigned int i = 0; i < sizeof(spawn_data); ++i) spawn_data[i] = i & 0xff; @@ -500,8 +619,8 @@ begin_shutdown: }; SceNpDrmKey * k_licensee = NULL; - int ret = sceNpDrmProcessExitSpawn2(k_licensee, self_path, (const char** const)spawn_argv, NULL, (sys_addr_t)spawn_data, 256, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M); - printf("ret: %x\n", ret); + int ret = sceNpDrmProcessExitSpawn2(k_licensee, g_settings.libsnes, (const char** const)spawn_argv, NULL, (sys_addr_t)spawn_data, 256, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M); + SSNES_LOG("Attempt to load SELF: [%s] (return code: [%x]).\n", g_settings.libsnes, ret); sceNpTerm(); cellSysmoduleUnloadModule(CELL_SYSMODULE_SYSUTIL_NP); cellSysmoduleUnloadModule(CELL_SYSMODULE_NET); diff --git a/ps3/menu.c b/ps3/menu.c index 252f42d829..07f323e689 100644 --- a/ps3/menu.c +++ b/ps3/menu.c @@ -808,6 +808,14 @@ static void select_file(uint32_t menu_id) strncpy(object, "Border image file", sizeof(object)); strncpy(comment, "INFO - Select a border image file from the menu by pressing the X button. ", sizeof(comment)); break; + case LIBSNES_CHOICE: + strncpy(dir_path, LIBSNES_DIR_PATH, sizeof(dir_path)); + strncpy(extensions, "self|SELF", sizeof(extensions)); + strncpy(title, "LIBSNES CORE SELECTION", sizeof(title)); + strncpy(object, "Libsnes", sizeof(object)); + strncpy(object, "Libsnes core file", sizeof(object)); + strncpy(comment, "INFO - Select a Libsnes core file from the menu by pressing the X button. ", sizeof(comment)); + break; EXTRA_SELECT_FILE_PART1(); } @@ -871,6 +879,12 @@ static void select_file(uint32_t menu_id) break; case BORDER_CHOICE: break; + case LIBSNES_CHOICE: + strlcpy(g_settings.libsnes, path, sizeof(g_settings.libsnes)); + g_console.return_to_launcher = true; + g_console.menu_enable = false; + g_console.mode_switch = MODE_EXIT; + break; EXTRA_SELECT_FILE_PART2(); } @@ -1950,9 +1964,11 @@ static void ingame_menu(uint32_t menu_id) case MENU_ITEM_CHANGE_LIBSNES: if(CTRL_CROSS(state)) { - g_console.return_to_launcher = true; - g_console.menu_enable = false; - g_console.mode_switch = MODE_EXIT; + menuStackindex++; + menuStack[menuStackindex] = menu_filebrowser; + menuStack[menuStackindex].enum_id = LIBSNES_CHOICE; + set_initial_dir_tmpbrowser = true; + set_delay = DELAY_LONG; } strcpy(comment, "Press 'CROSS' to choose a different emulator core."); break; @@ -2133,6 +2149,7 @@ void menu_loop(void) case SHADER_CHOICE: case PRESET_CHOICE: case BORDER_CHOICE: + case LIBSNES_CHOICE: case INPUT_PRESET_CHOICE: select_file(menuStack[menuStackindex].enum_id); break; diff --git a/ps3/menu.h b/ps3/menu.h index 83ca9a85a1..86bb1edec4 100644 --- a/ps3/menu.h +++ b/ps3/menu.h @@ -63,6 +63,7 @@ enum SHADER_CHOICE, PRESET_CHOICE, BORDER_CHOICE, + LIBSNES_CHOICE, PATH_SAVESTATES_DIR_CHOICE, PATH_DEFAULT_ROM_DIR_CHOICE, PATH_CHEATS_DIR_CHOICE, diff --git a/ps3/pkg/USRDIR/presets/.empty b/ps3/pkg/USRDIR/cores/.empty similarity index 100% rename from ps3/pkg/USRDIR/presets/.empty rename to ps3/pkg/USRDIR/cores/.empty diff --git a/ps3/pkg/USRDIR/borders/Menu/main-menu.png b/ps3/pkg/USRDIR/cores/borders/Menu/main-menu.png similarity index 100% rename from ps3/pkg/USRDIR/borders/Menu/main-menu.png rename to ps3/pkg/USRDIR/cores/borders/Menu/main-menu.png diff --git a/ps3/pkg/USRDIR/cores/presets/.empty b/ps3/pkg/USRDIR/cores/presets/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ps3/salamander/main.c b/ps3/salamander/main.c new file mode 100644 index 0000000000..c64f6f4a12 --- /dev/null +++ b/ps3/salamander/main.c @@ -0,0 +1,304 @@ +/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes. + * SSNES Salamander - A frontend for managing some pre-launch tasks. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * Copyright (C) 2011-2012 - Daniel De Matteis + * + * Some code herein may be based on code found in BSNES. + * + * SSNES 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SSNES 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 SSNES. + * If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../strl.h" +#include "../../conf/config_file.h" + +#define PATH_MAX (512UL) + +#define NP_POOL_SIZE (128*1024) +#define MAX_PATH_LENGTH 1024 + +#define SSNES_LOG(...) do { \ + fprintf(stderr, "SSNES Salamander: " __VA_ARGS__); \ + fflush(stderr); \ + } while (0) + +#define SSNES_ERR(...) do { \ + fprintf(stderr, "SSNES Salamander [ERROR] :: " __VA_ARGS__); \ + fflush(stderr); \ + } while (0) + +#define SSNES_WARN(...) do { \ + fprintf(stderr, "SSNES Salamander [WARN] :: " __VA_ARGS__); \ + fflush(stderr); \ + } while (0) + +static uint8_t np_pool[NP_POOL_SIZE]; +char contentInfoPath[MAX_PATH_LENGTH]; +char usrDirPath[MAX_PATH_LENGTH]; +char LIBSNES_DIR_PATH[MAX_PATH_LENGTH]; +char SYS_CONFIG_FILE[MAX_PATH_LENGTH]; +char libsnes_path[MAX_PATH_LENGTH]; + +SYS_PROCESS_PARAM(1001, 0x100000) + +static bool path_file_exists(const char *path) +{ + FILE *dummy = fopen(path, "rb"); + if (dummy) + { + fclose(dummy); + return true; + } + return false; +} + +static void dir_list_free(char **dir_list) +{ + if (!dir_list) + return; + + char **orig = dir_list; + while (*dir_list) + free(*dir_list++); + free(orig); +} + +static char **dir_list_new(const char *dir, const char *ext) +{ + size_t cur_ptr = 0; + size_t cur_size = 32; + char **dir_list = NULL; + + DIR *directory = NULL; + const struct dirent *entry = NULL; + + directory = opendir(dir); + if (!directory) + goto error; + + dir_list = (char**)calloc(cur_size, sizeof(char*)); + if (!dir_list) + goto error; + + while ((entry = readdir(directory))) + { + // Not a perfect search of course, but hopefully good enough in practice. + if (ext && !strstr(entry->d_name, ext)) + continue; + + dir_list[cur_ptr] = (char*)malloc(PATH_MAX); + if (!dir_list[cur_ptr]) + goto error; + + strlcpy(dir_list[cur_ptr], dir, PATH_MAX); + strlcat(dir_list[cur_ptr], "/", PATH_MAX); + strlcat(dir_list[cur_ptr], entry->d_name, PATH_MAX); + + cur_ptr++; + if (cur_ptr + 1 == cur_size) // Need to reserve for NULL. + { + cur_size *= 2; + dir_list = (char**)realloc(dir_list, cur_size * sizeof(char*)); + if (!dir_list) + goto error; + + // Make sure it's all NULL'd out since we cannot rely on realloc to do this. + memset(dir_list + cur_ptr, 0, (cur_size - cur_ptr) * sizeof(char*)); + } + } + + closedir(directory); + return dir_list; + +error: + SSNES_ERR("Failed to open directory: \"%s\"\n", dir); + if (directory) + closedir(directory); + dir_list_free(dir_list); + return NULL; +} + +static void find_and_set_first_file(void) +{ + //Last fallback - we'll need to start the first .SELF file + // we can find in the SSNES cores directory + char ** dir_list = dir_list_new(LIBSNES_DIR_PATH, ".SELF"); + if (!dir_list) + { + SSNES_ERR("Failed last fallback - SSNES Salamander will exit.\n"); + return; + } + + const char * first_self = dir_list[0]; + + if(first_self) + { + SSNES_LOG("Start first entry in libsnes cores dir: [%s].\n", first_self); + strlcpy(libsnes_path, first_self, sizeof(libsnes_path)); + } + else + { + SSNES_ERR("Failed last fallback - SSNES Salamander will exit.\n"); + } + + dir_list_free(dir_list); +} + +static void init_settings(void) +{ + char tmp_str[MAX_PATH_LENGTH]; + bool config_file_exists; + + + if(!path_file_exists(SYS_CONFIG_FILE)) + { + config_file_exists = false; + SSNES_ERR("Config file \"%s\" doesn't exist. Creating...\n", SYS_CONFIG_FILE); + FILE * f; + f = fopen(SYS_CONFIG_FILE, "w"); + fclose(f); + } + else + config_file_exists = true; + + + //try to find CORE.SELF + char core_self[1024]; + snprintf(core_self, sizeof(core_self), "%s/CORE.SELF", LIBSNES_DIR_PATH); + + if(path_file_exists(core_self)) + { + //Start CORE.SELF + snprintf(libsnes_path, sizeof(libsnes_path), core_self); + SSNES_LOG("Start [%s].\n", libsnes_path); + } + else + { + if(config_file_exists) + { + config_file_t * conf = config_file_new(SYS_CONFIG_FILE); + config_get_array(conf, "libsnes_path", tmp_str, sizeof(tmp_str)); + snprintf(libsnes_path, sizeof(libsnes_path), tmp_str); + } + + if(!config_file_exists || !strcmp(libsnes_path, "")) + find_and_set_first_file(); + else + { + SSNES_LOG("Start [%s] found in ssnes.cfg.\n", libsnes_path); + } + } +} + +static void get_environment_settings (void) +{ + unsigned int get_type; + unsigned int get_attributes; + CellGameContentSize size; + char dirName[CELL_GAME_DIRNAME_SIZE]; + + memset(&size, 0x00, sizeof(CellGameContentSize)); + + int ret = cellGameBootCheck(&get_type, &get_attributes, &size, dirName); + if(ret < 0) + { + SSNES_ERR("cellGameBootCheck() Error: 0x%x.\n", ret); + } + else + { + SSNES_LOG("cellGameBootCheck() OK.\n"); + SSNES_LOG("Directory name: [%s].\n", dirName); + SSNES_LOG(" HDD Free Size (in KB) = [%d] Size (in KB) = [%d] System Size (in KB) = [%d].\n", size.hddFreeSizeKB, size.sizeKB, size.sysSizeKB); + + switch(get_type) + { + case CELL_GAME_GAMETYPE_DISC: + SSNES_LOG("SSNES was launched on Optical Disc Drive.\n"); + break; + case CELL_GAME_GAMETYPE_HDD: + SSNES_LOG("SSNES was launched on HDD.\n"); + break; + } + + if((get_attributes & CELL_GAME_ATTRIBUTE_APP_HOME) == CELL_GAME_ATTRIBUTE_APP_HOME) + SSNES_LOG("SSNES was launched from host machine (APP_HOME).\n"); + + ret = cellGameContentPermit(contentInfoPath, usrDirPath); + + if(ret < 0) + { + SSNES_ERR("cellGameContentPermit() Error: 0x%x\n", ret); + } + else + { + SSNES_LOG("cellGameContentPermit() OK.\n"); + SSNES_LOG("contentInfoPath : [%s].\n", contentInfoPath); + SSNES_LOG("usrDirPath : [%s].\n", usrDirPath); + } + + /* now we fill in all the variables */ + snprintf(SYS_CONFIG_FILE, sizeof(SYS_CONFIG_FILE), "%s/ssnes.cfg", usrDirPath); + snprintf(LIBSNES_DIR_PATH, sizeof(LIBSNES_DIR_PATH), "%s/cores", usrDirPath); + } +} + +int main(int argc, char *argv[]) +{ + cellSysmoduleLoadModule(CELL_SYSMODULE_IO); + cellSysmoduleLoadModule(CELL_SYSMODULE_FS); + cellSysmoduleLoadModule(CELL_SYSMODULE_SYSUTIL_GAME); + cellSysmoduleLoadModule(CELL_SYSMODULE_NET); + cellSysmoduleLoadModule(CELL_SYSMODULE_SYSUTIL_NP); + + sys_net_initialize_network(); + + sceNpInit(NP_POOL_SIZE, np_pool); + + get_environment_settings(); + + init_settings(); + + char spawn_data[256]; + for(unsigned int i = 0; i < sizeof(spawn_data); ++i) + spawn_data[i] = i & 0xff; + + char spawn_data_size[16]; + sprintf(spawn_data_size, "%d", 256); + + const char * const spawn_argv[] = { + spawn_data_size, + "test argv for", + "sceNpDrmProcessExitSpawn2()", + NULL + }; + + SceNpDrmKey * k_licensee = NULL; + int ret = sceNpDrmProcessExitSpawn2(k_licensee, libsnes_path, (const char** const)spawn_argv, NULL, (sys_addr_t)spawn_data, 256, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M); + SSNES_LOG("Launch libsnes core: [%s] (return code: %x]).\n", libsnes_path, ret); + + sceNpTerm(); + cellSysmoduleUnloadModule(CELL_SYSMODULE_SYSUTIL_NP); + cellSysmoduleUnloadModule(CELL_SYSMODULE_NET); + cellSysmoduleUnloadModule(CELL_SYSMODULE_SYSUTIL_GAME); + cellSysmoduleLoadModule(CELL_SYSMODULE_FS); + cellSysmoduleLoadModule(CELL_SYSMODULE_IO); + + return 1; +} diff --git a/ps3/shared.h b/ps3/shared.h index 8ff934b9ab..64fbf4c54e 100644 --- a/ps3/shared.h +++ b/ps3/shared.h @@ -86,5 +86,6 @@ extern char BORDERS_DIR_PATH[MAX_PATH_LENGTH]; extern char SHADERS_DIR_PATH[MAX_PATH_LENGTH]; extern char DEFAULT_SHADER_FILE[MAX_PATH_LENGTH]; extern char DEFAULT_MENU_SHADER_FILE[MAX_PATH_LENGTH]; +extern char LIBSNES_DIR_PATH[MAX_PATH_LENGTH]; extern char SYS_CONFIG_FILE[MAX_PATH_LENGTH]; extern char MULTIMAN_GAME_TO_BOOT[MAX_PATH_LENGTH];