X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=frontend%2Flibretro.c;h=9be52f5dacdd39e86adc58966fdc5fe7b11b737f;hp=f44cc28bf8d653b41e942f25d62000067190e2b7;hb=354329faa304cfc2da1ef2f4ce9ef5e06c7d3489;hpb=93305561891374a32e3fccadb7d74c87f99502ef diff --git a/frontend/libretro.c b/frontend/libretro.c index f44cc28b..9be52f5d 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -5,6 +5,7 @@ * See the COPYING file in the top-level directory. */ +#define _GNU_SOURCE 1 // strcasestr #include #include #include @@ -17,6 +18,7 @@ #include "../libpcsxcore/cdriso.h" #include "../libpcsxcore/cheat.h" #include "../plugins/dfsound/out.h" +#include "../plugins/dfinput/externals.h" #include "cspace.h" #include "main.h" #include "plugin.h" @@ -49,6 +51,10 @@ int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 }; int in_keystate; int in_enable_vibration; +/* PSX max resolution is 640x512, but with enhancement it's 1024x512 */ +#define VOUT_MAX_WIDTH 1024 +#define VOUT_MAX_HEIGHT 512 + static void init_memcard(char *mcd_data) { unsigned off = 0; @@ -230,7 +236,24 @@ void out_register_libretro(struct out_driver *drv) } /* libretro */ -void retro_set_environment(retro_environment_t cb) { environ_cb = cb; } +void retro_set_environment(retro_environment_t cb) +{ + static const struct retro_variable vars[] = { + { "frameskip", "Frameskip; 0|1|2|3" }, + { "region", "Region; Auto|NTSC|PAL" }, +#ifdef __ARM_NEON__ + { "neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, + { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, + { "neon_enhancement_no_main", "Enhanced resolution speed hack; disabled|enabled" }, +#endif + { NULL, NULL }, + }; + + environ_cb = cb; + + cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars); +} + void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } void retro_set_audio_sample(retro_audio_sample_t cb) { (void)cb; } void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; } @@ -251,7 +274,7 @@ void retro_get_system_info(struct retro_system_info *info) memset(info, 0, sizeof(*info)); info->library_name = "PCSX-ReARMed"; info->library_version = "r19"; - info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn"; + info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn|m3u"; info->need_fullpath = true; } @@ -262,8 +285,8 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->timing.sample_rate = 44100; info->geometry.base_width = 320; info->geometry.base_height = 240; - info->geometry.max_width = 640; - info->geometry.max_height = 512; + info->geometry.max_width = VOUT_MAX_WIDTH; + info->geometry.max_height = VOUT_MAX_HEIGHT; info->geometry.aspect_ratio = 4.0 / 3.0; } @@ -394,6 +417,7 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) /* multidisk support */ static bool disk_ejected; static unsigned int disk_current_index; +static unsigned int disk_count; static struct disks_state { char *fname; int internal_index; // for multidisk eboots @@ -463,14 +487,7 @@ static bool disk_set_image_index(unsigned int index) static unsigned int disk_get_num_images(void) { - unsigned int count = 0; - size_t i; - - for (i = 0; i < sizeof(disks) / sizeof(disks[0]); i++) - if (disks[i].fname != NULL) - count++; - - return count; + return disk_count; } static bool disk_replace_image_index(unsigned index, @@ -500,7 +517,10 @@ static bool disk_replace_image_index(unsigned index, static bool disk_add_image_index(void) { - // TODO?? + if (disk_count >= 8) + return false; + + disk_count++; return true; } @@ -514,9 +534,68 @@ static struct retro_disk_control_callback disk_control = { .add_image_index = disk_add_image_index, }; +// just in case, maybe a win-rt port in the future? +#ifdef _WIN32 +#define SLASH '\\' +#else +#define SLASH '/' +#endif + +static char base_dir[PATH_MAX]; + +static bool read_m3u(const char *file) +{ + char line[PATH_MAX]; + char name[PATH_MAX]; + FILE *f = fopen(file, "r"); + if (!f) + return false; + + while (fgets(line, sizeof(line), f) && disk_count < sizeof(disks) / sizeof(disks[0])) { + if (line[0] == '#') + continue; + char *carrige_return = strchr(line, '\r'); + if (carrige_return) + *carrige_return = '\0'; + char *newline = strchr(line, '\n'); + if (newline) + *newline = '\0'; + + if (line[0] != '\0') + { + snprintf(name, sizeof(name), "%s%c%s", base_dir, SLASH, line); + disks[disk_count++].fname = strdup(name); + } + } + + fclose(f); + return (disk_count != 0); +} + +static void extract_directory(char *buf, const char *path, size_t size) +{ + char *base; + strncpy(buf, path, size - 1); + buf[size - 1] = '\0'; + + base = strrchr(buf, '/'); + if (!base) + base = strrchr(buf, '\\'); + + if (base) + *base = '\0'; + else + { + buf[0] = '.'; + buf[1] = '\0'; + } +} + bool retro_load_game(const struct retro_game_info *info) { size_t i; + bool is_m3u = (strcasestr(info->path, ".m3u") != NULL); + #ifdef FRONTEND_SUPPORTS_RGB565 enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565; if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { @@ -543,7 +622,17 @@ bool retro_load_game(const struct retro_game_info *info) } disk_current_index = 0; - disks[0].fname = strdup(info->path); + extract_directory(base_dir, info->path, sizeof(base_dir)); + + if (is_m3u) { + if (!read_m3u(info->path)) { + SysPrintf("failed to read m3u file\n"); + return false; + } + } else { + disk_count = 1; + disks[0].fname = strdup(info->path); + } set_cd_image(disks[0].fname); @@ -562,6 +651,7 @@ bool retro_load_game(const struct retro_game_info *info) } plugin_call_rearmed_cbs(); + dfinput_activate(); Config.PsxAuto = 1; if (CheckCdrom() == -1) { @@ -578,9 +668,12 @@ bool retro_load_game(const struct retro_game_info *info) emu_on_new_cd(0); // multidisk images - for (i = 1; i < sizeof(disks) / sizeof(disks[0]) && i < cdrIsoMultidiskCount; i++) { - disks[i].fname = strdup(info->path); - disks[i].internal_index = i; + if (!is_m3u) { + disk_count = cdrIsoMultidiskCount < 8 ? cdrIsoMultidiskCount : 8; + for (i = 1; i < sizeof(disks) / sizeof(disks[0]) && i < cdrIsoMultidiskCount; i++) { + disks[i].fname = strdup(info->path); + disks[i].internal_index = i; + } } return true; @@ -602,12 +695,18 @@ unsigned retro_get_region(void) void *retro_get_memory_data(unsigned id) { - return Mcd1Data; + if (id == RETRO_MEMORY_SAVE_RAM) + return Mcd1Data; + else + return NULL; } size_t retro_get_memory_size(unsigned id) { - return MCD_SIZE; + if (id == RETRO_MEMORY_SAVE_RAM) + return MCD_SIZE; + else + return 0; } void retro_reset(void) @@ -635,11 +734,87 @@ static const unsigned short retro_psx_map[] = { }; #define RETRO_PSX_MAP_LEN (sizeof(retro_psx_map) / sizeof(retro_psx_map[0])) +static void update_variables(bool in_flight) +{ + struct retro_variable var; + + var.value = NULL; + var.key = "frameskip"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + pl_rearmed_cbs.frameskip = atoi(var.value); + + var.value = NULL; + var.key = "region"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + Config.PsxAuto = 0; + if (strcmp(var.value, "Automatic") == 0) + Config.PsxAuto = 1; + else if (strcmp(var.value, "NTSC") == 0) + Config.PsxType = 0; + else if (strcmp(var.value, "PAL") == 0) + Config.PsxType = 1; + } +#ifdef __ARM_NEON__ + var.value = "NULL"; + var.key = "neon_interlace_enable"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "disabled") == 0) + pl_rearmed_cbs.gpu_neon.allow_interlace = 0; + else if (strcmp(var.value, "enabled") == 0) + pl_rearmed_cbs.gpu_neon.allow_interlace = 1; + } + + var.value = NULL; + var.key = "neon_enhancement_enable"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "disabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_enable = 0; + else if (strcmp(var.value, "enabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_enable = 1; + } + + var.value = NULL; + var.key = "neon_enhancement_no_main"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "disabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_no_main = 0; + else if (strcmp(var.value, "enabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_no_main = 1; + } +#endif + + if (in_flight) { + // inform core things about possible config changes + plugin_call_rearmed_cbs(); + + if (GPU_open != NULL && GPU_close != NULL) { + GPU_close(); + GPU_open(&gpuDisp, "PCSX", NULL); + } + + dfinput_activate(); + } +} + void retro_run(void) { int i; input_poll_cb(); + + bool updated = false; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) + update_variables(true); + in_keystate = 0; for (i = 0; i < RETRO_PSX_MAP_LEN; i++) if (input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, i)) @@ -674,7 +849,7 @@ void retro_init(void) exit(1); } - vout_buf = malloc(640 * 512 * 2); + vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) { @@ -694,7 +869,15 @@ void retro_init(void) fclose(f); } else + { SysPrintf("no BIOS files found.\n"); + struct retro_message msg = + { + "no BIOS found, expect bugs!", + 180 + }; + environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&msg); + } level = 1; environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); @@ -720,6 +903,8 @@ void retro_init(void) SaveFuncs.write = save_write; SaveFuncs.seek = save_seek; SaveFuncs.close = save_close; + + update_variables(false); } void retro_deinit(void)