/* RetroArch - A frontend for libretro. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * Copyright (C) 2011-2015 - Daniel De Matteis * * RetroArch 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. * * RetroArch 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 RetroArch. * If not, see . */ #include #include #include #include #include #include #include #include #include #include "../../gfx/drivers/psp_sdk_defines.h" #include #include "../../general.h" #if defined(HAVE_KERNEL_PRX) || defined(IS_SALAMANDER) #include "../../psp1/kernel_functions.h" #endif PSP_MODULE_INFO("RetroArch PSP", 0, 1, 1); PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER|THREAD_ATTR_VFPU); #ifdef BIG_STACK PSP_MAIN_THREAD_STACK_SIZE_KB(4*1024); #endif PSP_HEAP_SIZE_MAX(); char eboot_path[512]; static bool exit_spawn = false; static bool exitspawn_start_game = false; #ifdef IS_SALAMANDER #include "../../file_ext.h" #endif static void frontend_psp_get_environment_settings(int *argc, char *argv[], void *args, void *params_data) { (void)args; #ifndef IS_SALAMANDER g_extern.verbosity = true; #if defined(HAVE_LOGGER) logger_init(); #elif defined(HAVE_FILE_LOGGER) g_extern.log_file = fopen("ms0:/retroarch-log.txt", "w"); #endif #endif strlcpy(eboot_path, argv[0], sizeof(eboot_path)); fill_pathname_basedir(g_defaults.port_dir, argv[0], sizeof(g_defaults.port_dir)); RARCH_LOG("port dir: [%s]\n", g_defaults.port_dir); fill_pathname_join(g_defaults.assets_dir, g_defaults.port_dir, "media", sizeof(g_defaults.assets_dir)); fill_pathname_join(g_defaults.core_dir, g_defaults.port_dir, "cores", sizeof(g_defaults.core_dir)); fill_pathname_join(g_defaults.core_info_dir, g_defaults.port_dir, "cores", sizeof(g_defaults.core_info_dir)); fill_pathname_join(g_defaults.savestate_dir, g_defaults.core_dir, "savestates", sizeof(g_defaults.savestate_dir)); fill_pathname_join(g_defaults.sram_dir, g_defaults.core_dir, "savefiles", sizeof(g_defaults.sram_dir)); fill_pathname_join(g_defaults.system_dir, g_defaults.core_dir, "system", sizeof(g_defaults.system_dir)); fill_pathname_join(g_defaults.playlist_dir, g_defaults.core_dir, "playlists", sizeof(g_defaults.playlist_dir)); fill_pathname_join(g_defaults.config_path, g_defaults.port_dir, "retroarch.cfg", sizeof(g_defaults.config_path)); #ifndef IS_SALAMANDER if (argv[1] && (argv[1][0] != '\0')) { static char path[PATH_MAX_LENGTH]; struct rarch_main_wrap *args = NULL; *path = '\0'; args = (struct rarch_main_wrap*)params_data; if (args) { strlcpy(path, argv[1], sizeof(path)); args->touched = true; args->no_content = false; args->verbose = false; args->config_path = NULL; args->sram_path = NULL; args->state_path = NULL; args->content_path = path; args->libretro_path = NULL; RARCH_LOG("argv[0]: %s\n", argv[0]); RARCH_LOG("argv[1]: %s\n", argv[1]); RARCH_LOG("argv[2]: %s\n", argv[2]); RARCH_LOG("Auto-start game %s.\n", argv[1]); } } #endif } static void frontend_psp_deinit(void *data) { (void)data; #ifndef IS_SALAMANDER g_extern.verbosity = false; #ifdef HAVE_FILE_LOGGER if (g_extern.log_file) fclose(g_extern.log_file); g_extern.log_file = NULL; #endif #endif } static void frontend_psp_shutdown(bool unused) { (void)unused; sceKernelExitGame(); } static int exit_callback(int arg1, int arg2, void *common) { frontend_psp_deinit(NULL); frontend_psp_shutdown(false); return 0; } int callback_thread(SceSize args, void *argp) { int cbid = sceKernelCreateCallback("Exit callback", exit_callback, NULL); sceKernelRegisterExitCallback(cbid); sceKernelSleepThreadCB(); return 0; } static int setup_callback(void) { int thread_id = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0); if (thread_id >= 0) sceKernelStartThread(thread_id, 0, 0); return thread_id; } static void frontend_psp_init(void *data) { #ifndef IS_SALAMANDER (void)data; //initialize debug screen pspDebugScreenInit(); pspDebugScreenClear(); setup_callback(); pspFpuSetEnable(0);//disable FPU exceptions scePowerSetClockFrequency(333,333,166); #endif #if defined(HAVE_KERNEL_PRX) || defined(IS_SALAMANDER) pspSdkLoadStartModule("kernel_functions.prx", PSP_MEMORY_PARTITION_KERNEL); #endif } static void frontend_psp_exec(const char *path, bool should_load_game) { #if defined(HAVE_KERNEL_PRX) || defined(IS_SALAMANDER) char argp[512]; SceSize args = 0; argp[0] = '\0'; strlcpy(argp, eboot_path, sizeof(argp)); args = strlen(argp) + 1; #ifndef IS_SALAMANDER if (should_load_game && g_extern.fullpath[0] != '\0') { argp[args] = '\0'; strlcat(argp + args, g_extern.fullpath, sizeof(argp) - args); args += strlen(argp + args) + 1; } #endif RARCH_LOG("Attempt to load executable: [%s].\n", path); exitspawn_kernel(path, args, argp); #endif } static void frontend_psp_set_fork(bool exit, bool start_game) { exit_spawn = true; exitspawn_start_game = start_game; } static void frontend_psp_exitspawn(char *core_path, size_t sizeof_core_path) { bool should_load_game = false; #ifndef IS_SALAMANDER should_load_game = exitspawn_start_game; if (!exit_spawn) return; #endif frontend_psp_exec(core_path, should_load_game); } static int frontend_psp_get_rating(void) { return 4; } const frontend_ctx_driver_t frontend_ctx_psp = { frontend_psp_get_environment_settings, /* get_environment_settings */ frontend_psp_init, /* init */ frontend_psp_deinit, /* deinit */ frontend_psp_exitspawn, /* exitspawn */ NULL, /* process_args */ frontend_psp_exec, /* exec */ frontend_psp_set_fork, /* set_fork */ frontend_psp_shutdown, /* shutdown */ NULL, /* get_name */ frontend_psp_get_rating, /* get_rating */ NULL, /* load_content */ "psp", };