X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=frontend%2Flibretro.c;h=9e73fc7a8b1bc798187037b89dff5de8ca739ba9;hp=4f6879ed5ea40c4fb4461199ad6dce2c2b57d859;hb=b40a83db932d2c2a250e68a06e88a334509968ec;hpb=17f84149a604fefb8181a280487bd48ca7a353b2 diff --git a/frontend/libretro.c b/frontend/libretro.c index 4f6879ed..9e73fc7a 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -13,9 +13,11 @@ #include "../libpcsxcore/psxcounters.h" #include "../libpcsxcore/psxmem_map.h" #include "../libpcsxcore/new_dynarec/new_dynarec.h" +#include "../libpcsxcore/cdrom.h" +#include "../libpcsxcore/cdriso.h" #include "../libpcsxcore/cheat.h" #include "../plugins/dfsound/out.h" -#include "../plugins/gpulib/cspace.h" +#include "cspace.h" #include "main.h" #include "plugin.h" #include "plugin_lib.h" @@ -248,8 +250,8 @@ void retro_get_system_info(struct retro_system_info *info) { memset(info, 0, sizeof(*info)); info->library_name = "PCSX-ReARMed"; - info->library_version = REV; - info->valid_extensions = "bin|cue|img|mdf|pbp|cbn"; + info->library_version = "r19"; + info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn|m3u"; info->need_fullpath = true; } @@ -363,6 +365,7 @@ bool retro_unserialize(const void *data, size_t size) return ret == 0 ? true : false; } +/* cheats */ void retro_cheat_reset(void) { ClearAllCheats(); @@ -388,8 +391,192 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) Cheats[index].Enabled = enabled; } +/* multidisk support */ +static bool disk_ejected; +static unsigned int disk_current_index; +static struct disks_state { + char *fname; + int internal_index; // for multidisk eboots +} disks[8]; + +static bool disk_set_eject_state(bool ejected) +{ + // weird PCSX API.. + SetCdOpenCaseTime(ejected ? -1 : (time(NULL) + 2)); + LidInterrupt(); + + disk_ejected = ejected; + return true; +} + +static bool disk_get_eject_state(void) +{ + /* can't be controlled by emulated software */ + return disk_ejected; +} + +static unsigned int disk_get_image_index(void) +{ + return disk_current_index; +} + +static bool disk_set_image_index(unsigned int index) +{ + if (index >= sizeof(disks) / sizeof(disks[0])) + return false; + + CdromId[0] = '\0'; + CdromLabel[0] = '\0'; + + if (disks[index].fname == NULL) { + SysPrintf("missing disk #%u\n", index); + CDR_shutdown(); + + // RetroArch specifies "no disk" with index == count, + // so don't fail here.. + disk_current_index = index; + return true; + } + + SysPrintf("switching to disk %u: \"%s\" #%d\n", index, + disks[index].fname, disks[index].internal_index); + + cdrIsoMultidiskSelect = disks[index].internal_index; + set_cd_image(disks[index].fname); + if (ReloadCdromPlugin() < 0) { + SysPrintf("failed to load cdr plugin\n"); + return false; + } + if (CDR_open() < 0) { + SysPrintf("failed to open cdr plugin\n"); + return false; + } + + if (!disk_ejected) { + SetCdOpenCaseTime(time(NULL) + 2); + LidInterrupt(); + } + + disk_current_index = index; + return true; +} + +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; +} + +static bool disk_replace_image_index(unsigned index, + const struct retro_game_info *info) +{ + char *old_fname; + bool ret = true; + + if (index >= sizeof(disks) / sizeof(disks[0])) + return false; + + old_fname = disks[index].fname; + disks[index].fname = NULL; + disks[index].internal_index = 0; + + if (info != NULL) { + disks[index].fname = strdup(info->path); + if (index == disk_current_index) + ret = disk_set_image_index(index); + } + + if (old_fname != NULL) + free(old_fname); + + return ret; +} + +static bool disk_add_image_index(void) +{ + // TODO?? + return true; +} + +static struct retro_disk_control_callback disk_control = { + .set_eject_state = disk_set_eject_state, + .get_eject_state = disk_get_eject_state, + .get_image_index = disk_get_image_index, + .set_image_index = disk_set_image_index, + .get_num_images = disk_get_num_images, + .replace_image_index = disk_replace_image_index, + .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]; + size_t i = 0; + FILE *f = fopen(file, "r"); + if (!f) + return false; + + while (fgets(line, sizeof(line), f) && i < 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[i++].fname = strdup(name); + } + } + + fclose(f); + return (i != 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)) { @@ -397,12 +584,37 @@ bool retro_load_game(const struct retro_game_info *info) } #endif + if (info == NULL || info->path == NULL) { + SysPrintf("info->path required\n"); + return false; + } + if (plugins_opened) { ClosePlugins(); plugins_opened = 0; } - set_cd_image(info->path); + for (i = 0; i < sizeof(disks) / sizeof(disks[0]); i++) { + if (disks[i].fname != NULL) { + free(disks[i].fname); + disks[i].fname = NULL; + } + disks[i].internal_index = 0; + } + + disk_current_index = 0; + 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 + disks[0].fname = strdup(info->path); + + set_cd_image(disks[0].fname); /* have to reload after set_cd_image for correct cdr plugin */ if (LoadPlugins() == -1) { @@ -434,6 +646,14 @@ bool retro_load_game(const struct retro_game_info *info) } emu_on_new_cd(0); + // multidisk images + if (!is_m3u) { + 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; } @@ -453,12 +673,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) @@ -551,6 +777,7 @@ void retro_init(void) environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); environ_cb(RETRO_ENVIRONMENT_GET_CAN_DUPE, &vout_can_dupe); + environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_control); /* Set how much slower PSX CPU runs * 100 (so that 200 is 2 times) * we have to do this because cache misses and some IO penalties