X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=frontend%2Flibretro.c;h=4c285cfbc26f83b34cc7f8e92cabb4ff3668a00c;hp=cf875beb4bf16c2b90b91d5b13b93ec85a24c79c;hb=HEAD;hpb=91da8e32287f181a870140fdcc8fcdac7bafdebe diff --git a/frontend/libretro.c b/frontend/libretro.c index cf875beb..6a719ae4 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -15,6 +15,7 @@ #include #endif +#include "retro_miscellaneous.h" #ifdef SWITCH #include #endif @@ -76,6 +77,13 @@ static retro_set_rumble_state_t rumble_cb; static struct retro_log_callback logging; static retro_log_printf_t log_cb; +#define LogWarn(fmt, ...) do { \ + if (log_cb) log_cb(RETRO_LOG_WARN, fmt, ##__VA_ARGS__); \ +} while (0) +#define LogErr(fmt, ...) do { \ + if (log_cb) log_cb(RETRO_LOG_ERROR, fmt, ##__VA_ARGS__); \ +} while (0) + static unsigned msg_interface_version = 0; static void *vout_buf; @@ -84,7 +92,6 @@ static int vout_width = 256, vout_height = 240, vout_pitch = 256; static int vout_fb_dirty; static int psx_w, psx_h; static bool vout_can_dupe; -static bool duping_enable; static bool found_bios; static bool display_internal_fps = false; static unsigned frame_count = 0; @@ -124,7 +131,8 @@ static unsigned previous_width = 0; static unsigned previous_height = 0; static int plugins_opened; -static int is_pal_mode; + +#define is_pal_mode Config.PsxType /* memory card data */ extern char Mcd1Data[MCD_SIZE]; @@ -145,7 +153,9 @@ int in_mouse[8][2]; int multitap1 = 0; int multitap2 = 0; int in_enable_vibration = 1; -int in_enable_crosshair[2] = { 0, 0 }; +static int in_enable_crosshair[2] = { 0, 0 }; +static int in_dualshock_analog_combo = 0; +static bool in_dualshock_toggling = false; // NegCon adjustment parameters // > The NegCon 'twist' action is somewhat awkward when mapped @@ -235,10 +245,13 @@ static void set_vout_fb() fb.access_flags = RETRO_MEMORY_ACCESS_WRITE; vout_pitch = vout_width; - if (environ_cb(RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER, &fb) && fb.format == RETRO_PIXEL_FORMAT_RGB565) { + if (environ_cb(RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER, &fb) + && fb.format == RETRO_PIXEL_FORMAT_RGB565 + && vout_can_dupe) + { vout_buf_ptr = fb.data; if (fb.pitch / 2 != vout_pitch && fb.pitch != vout_width * 2) - SysPrintf("got unusual pitch %zd for resolution %dx%d\n", fb.pitch, vout_width, vout_height); + LogWarn("got unusual pitch %zd for resolution %dx%d\n", fb.pitch, vout_width, vout_height); vout_pitch = fb.pitch / 2; } else @@ -282,16 +295,17 @@ static void convert(void *buf, size_t bytes) static void addCrosshair(int port, int crosshair_color, unsigned short *buffer, int bufferStride, int pos_x, int pos_y, int thickness, int size_x, int size_y) { for (port = 0; port < 2; port++) { // Draw the horizontal line of the crosshair - for (int i = pos_y - thickness / 2; i <= pos_y + thickness / 2; i++) { - for (int j = pos_x - size_x / 2; j <= pos_x + size_x / 2; j++) { + int i, j; + for (i = pos_y - thickness / 2; i <= pos_y + thickness / 2; i++) { + for (j = pos_x - size_x / 2; j <= pos_x + size_x / 2; j++) { if ((i + vout_height) >= 0 && (i + vout_height) < bufferStride && j >= 0 && j < bufferStride && in_enable_crosshair[port] > 0) buffer[i * bufferStride + j] = crosshair_color; - } } + } // Draw the vertical line of the crosshair - for (int i = pos_x - thickness / 2; i <= pos_x + thickness / 2; i++) { - for (int j = pos_y - size_y / 2; j <= pos_y + size_y / 2; j++) { + for (i = pos_x - thickness / 2; i <= pos_x + thickness / 2; i++) { + for (j = pos_y - size_y / 2; j <= pos_y + size_y / 2; j++) { if (i >= 0 && i < bufferStride && (j + vout_height) >= 0 && (j + vout_height) < bufferStride && in_enable_crosshair[port] > 0) buffer[j * bufferStride + i] = crosshair_color; } @@ -354,8 +368,8 @@ static void vout_flip(const void *vram, int stride, int bgr24, for (port = 0; port < 2; port++) { if (in_enable_crosshair[port] > 0 && (in_type[port] == PSE_PAD_TYPE_GUNCON || in_type[port] == PSE_PAD_TYPE_GUN)) { - struct CrosshairInfo crosshairInfo; - CrosshairDimensions(port, &crosshairInfo); + struct CrosshairInfo crosshairInfo; + CrosshairDimensions(port, &crosshairInfo); addCrosshair(port, in_enable_crosshair[port], dest, dstride, crosshairInfo.pos_x, crosshairInfo.pos_y, crosshairInfo.thickness, crosshairInfo.size_x, crosshairInfo.size_y); } } @@ -407,7 +421,7 @@ void *pl_3ds_mmap(unsigned long addr, size_t size, int is_fixed, if (svcControlMemory(&tmp, (void *)custom_map->target_map, (void *)ptr_aligned, size, MEMOP_MAP, 0x3) < 0) { - SysPrintf("could not map memory @0x%08X\n", custom_map->target_map); + LogErr("could not map memory @0x%08X\n", custom_map->target_map); exit(1); } @@ -573,7 +587,6 @@ void pl_frame_limit(void) void pl_timing_prepare(int is_pal) { - is_pal_mode = is_pal; } void plat_trigger_vibrate(int pad, int low, int high) @@ -715,8 +728,8 @@ static bool update_option_visibility(void) "pcsx_rearmed_negcon_deadzone", "pcsx_rearmed_negcon_response", "pcsx_rearmed_input_sensitivity", - "pcsx_rearmed_crosshair1", - "pcsx_rearmed_crosshair2", + "pcsx_rearmed_crosshair1", + "pcsx_rearmed_crosshair2", "pcsx_rearmed_konamigunadjustx", "pcsx_rearmed_konamigunadjusty", "pcsx_rearmed_gunconadjustx", @@ -978,7 +991,7 @@ void retro_get_system_info(struct retro_system_info *info) #endif memset(info, 0, sizeof(*info)); info->library_name = "PCSX-ReARMed"; - info->library_version = "r23l" GIT_VERSION; + info->library_version = "r24l" GIT_VERSION; info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn|m3u|chd|iso|exe"; info->need_fullpath = true; } @@ -989,7 +1002,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) unsigned geom_width = vout_width; memset(info, 0, sizeof(*info)); - info->timing.fps = is_pal_mode ? 50.0 : 60.0; + info->timing.fps = psxGetFps(); info->timing.sample_rate = 44100.0; info->geometry.base_width = geom_width; info->geometry.base_height = geom_height; @@ -1080,7 +1093,7 @@ static void save_close(void *file) return; if (fp->pos > r_size) - SysPrintf("ERROR: save buffer overflow detected\n"); + LogErr("ERROR: save buffer overflow detected\n"); else if (fp->is_write && fp->pos < r_size) // make sure we don't save trash in leftover space memset(fp->buf + fp->pos, 0, r_size - fp->pos); @@ -1151,7 +1164,7 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) finish: if (ret != 0) - SysPrintf("Failed to set cheat %#u\n", index); + LogErr("Failed to set cheat %#u\n", index); else if (index < NumCheats) Cheats[index].Enabled = enabled; free(buf); @@ -1226,12 +1239,31 @@ static void disk_init(void) } } +#ifdef HAVE_CDROM +static long CALLBACK rcdrom_open(void); +static long CALLBACK rcdrom_close(void); +static void rcdrom_stop_thread(void); +#endif + static bool disk_set_eject_state(bool ejected) { - // weird PCSX API.. + if (ejected != disk_ejected) + SysPrintf("new eject_state: %d\n", ejected); + + // weird PCSX API... SetCdOpenCaseTime(ejected ? -1 : (time(NULL) + 2)); LidInterrupt(); +#ifdef HAVE_CDROM + if (CDR_open == rcdrom_open && ejected != disk_ejected) { + rcdrom_stop_thread(); + if (!ejected) { + // likely the real cd was also changed - rescan + rcdrom_close(); + rcdrom_open(); + } + } +#endif disk_ejected = ejected; return true; } @@ -1257,7 +1289,7 @@ static bool disk_set_image_index(unsigned int index) if (disks[index].fname == NULL) { - SysPrintf("missing disk #%u\n", index); + LogErr("missing disk #%u\n", index); CDR_shutdown(); // RetroArch specifies "no disk" with index == count, @@ -1266,26 +1298,25 @@ static bool disk_set_image_index(unsigned int index) return true; } - SysPrintf("switching to disk %u: \"%s\" #%d\n", index, + LogErr("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"); + LogErr("failed to load cdr plugin\n"); return false; } if (CDR_open() < 0) { - SysPrintf("failed to open cdr plugin\n"); + LogErr("failed to open cdr plugin\n"); return false; } if (!disk_ejected) { - SetCdOpenCaseTime(time(NULL) + 2); - LidInterrupt(); + disk_set_eject_state(disk_ejected); } disk_current_index = index; @@ -1486,6 +1517,308 @@ static void extract_directory(char *buf, const char *path, size_t size) } } +// raw cdrom support +#ifdef HAVE_CDROM +#include "vfs/vfs_implementation.h" +#include "vfs/vfs_implementation_cdrom.h" +#include "libretro-cdrom.h" +#include "rthreads/rthreads.h" +#include "retro_timers.h" +struct cached_buf { + unsigned char buf[2352]; + unsigned int lba; +}; +static struct { + libretro_vfs_implementation_file *h; + sthread_t *thread; + slock_t *read_lock; + slock_t *buf_lock; + scond_t *cond; + struct cached_buf *buf; + unsigned int buf_cnt, thread_exit, do_prefetch; + unsigned int total_lba, prefetch_lba; + int check_eject_delay; +} rcdrom; + +static void lbacache_do(unsigned int lba) +{ + unsigned char m, s, f, buf[2352]; + unsigned int i = lba % rcdrom.buf_cnt; + int ret; + + cdrom_lba_to_msf(lba + 150, &m, &s, &f); + slock_lock(rcdrom.read_lock); + ret = cdrom_read_sector(rcdrom.h, lba, buf); + slock_lock(rcdrom.buf_lock); + slock_unlock(rcdrom.read_lock); + //printf("%d:%02d:%02d m%d f%d\n", m, s, f, buf[12+3], ((buf[12+4+2] >> 5) & 1) + 1); + if (ret) { + rcdrom.do_prefetch = 0; + slock_unlock(rcdrom.buf_lock); + LogErr("prefetch: cdrom_read_sector failed for lba %d\n", lba); + return; + } + rcdrom.check_eject_delay = 100; + + if (lba != rcdrom.buf[i].lba) { + memcpy(rcdrom.buf[i].buf, buf, sizeof(rcdrom.buf[i].buf)); + rcdrom.buf[i].lba = lba; + } + slock_unlock(rcdrom.buf_lock); + retro_sleep(0); // why does the main thread stall without this? +} + +static int lbacache_get(unsigned int lba, void *buf) +{ + unsigned int i; + int ret = 0; + + i = lba % rcdrom.buf_cnt; + slock_lock(rcdrom.buf_lock); + if (lba == rcdrom.buf[i].lba) { + memcpy(buf, rcdrom.buf[i].buf, 2352); + ret = 1; + } + slock_unlock(rcdrom.buf_lock); + return ret; +} + +static void rcdrom_prefetch_thread(void *unused) +{ + unsigned int buf_cnt, lba, lba_to; + + slock_lock(rcdrom.buf_lock); + while (!rcdrom.thread_exit) + { +#ifdef __GNUC__ + __asm__ __volatile__("":::"memory"); // barrier +#endif + if (!rcdrom.do_prefetch) + scond_wait(rcdrom.cond, rcdrom.buf_lock); + if (!rcdrom.do_prefetch || !rcdrom.h || rcdrom.thread_exit) + continue; + + buf_cnt = rcdrom.buf_cnt; + lba = rcdrom.prefetch_lba; + lba_to = lba + buf_cnt; + if (lba_to > rcdrom.total_lba) + lba_to = rcdrom.total_lba; + for (; lba < lba_to; lba++) { + if (lba != rcdrom.buf[lba % buf_cnt].lba) + break; + } + if (lba == lba_to) { + // caching complete + rcdrom.do_prefetch = 0; + continue; + } + + slock_unlock(rcdrom.buf_lock); + lbacache_do(lba); + slock_lock(rcdrom.buf_lock); + } + slock_unlock(rcdrom.buf_lock); +} + +static void rcdrom_stop_thread(void) +{ + rcdrom.thread_exit = 1; + if (rcdrom.buf_lock) { + slock_lock(rcdrom.buf_lock); + rcdrom.do_prefetch = 0; + if (rcdrom.cond) + scond_signal(rcdrom.cond); + slock_unlock(rcdrom.buf_lock); + } + if (rcdrom.thread) { + sthread_join(rcdrom.thread); + rcdrom.thread = NULL; + } + if (rcdrom.cond) { scond_free(rcdrom.cond); rcdrom.cond = NULL; } + if (rcdrom.buf_lock) { slock_free(rcdrom.buf_lock); rcdrom.buf_lock = NULL; } + if (rcdrom.read_lock) { slock_free(rcdrom.read_lock); rcdrom.read_lock = NULL; } + free(rcdrom.buf); + rcdrom.buf = NULL; +} + +// the thread is optional, if anything fails we can do direct reads +static void rcdrom_start_thread(void) +{ + rcdrom_stop_thread(); + rcdrom.thread_exit = rcdrom.prefetch_lba = rcdrom.do_prefetch = 0; + if (rcdrom.buf_cnt == 0) + return; + rcdrom.buf = calloc(rcdrom.buf_cnt, sizeof(rcdrom.buf[0])); + rcdrom.buf_lock = slock_new(); + rcdrom.read_lock = slock_new(); + rcdrom.cond = scond_new(); + if (rcdrom.buf && rcdrom.buf_lock && rcdrom.read_lock && rcdrom.cond) { + rcdrom.thread = sthread_create(rcdrom_prefetch_thread, NULL); + rcdrom.buf[0].lba = ~0; + } + if (!rcdrom.thread) { + LogErr("cdrom precache thread init failed.\n"); + rcdrom_stop_thread(); + } +} + +static long CALLBACK rcdrom_open(void) +{ + const char *name = GetIsoFile(); + //printf("%s %s\n", __func__, name); + rcdrom.h = retro_vfs_file_open_impl(name, RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + if (rcdrom.h) { + int ret = cdrom_set_read_speed_x(rcdrom.h, 4); + if (ret) LogErr("CD speed set failed\n"); + const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc(); + const cdrom_track_t *last = &toc->track[toc->num_tracks - 1]; + unsigned int lba = cdrom_msf_to_lba(last->min, last->sec, last->frame) - 150; + rcdrom.total_lba = lba + last->track_size; + //cdrom_get_current_config_random_readable(rcdrom.h); + //cdrom_get_current_config_multiread(rcdrom.h); + //cdrom_get_current_config_cdread(rcdrom.h); + //cdrom_get_current_config_profiles(rcdrom.h); + rcdrom_start_thread(); + return 0; + } + LogErr("retro_vfs_file_open failed for '%s'\n", name); + return -1; +} + +static long CALLBACK rcdrom_close(void) +{ + //printf("%s\n", __func__); + if (rcdrom.h) { + rcdrom_stop_thread(); + retro_vfs_file_close_impl(rcdrom.h); + rcdrom.h = NULL; + } + return 0; +} + +static long CALLBACK rcdrom_getTN(unsigned char *tn) +{ + const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc(); + tn[0] = 1; + tn[1] = toc->num_tracks; + //printf("%s -> %d %d\n", __func__, tn[0], tn[1]); + return 0; +} + +static long CALLBACK rcdrom_getTD(unsigned char track, unsigned char *rt) +{ + const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc(); + rt[0] = 0, rt[1] = 2, rt[2] = 0; + if (track == 0) { + cdrom_lba_to_msf(rcdrom.total_lba + 150, &rt[2], &rt[1], &rt[0]); + } + else if (track <= toc->num_tracks) { + int i = track - 1; + rt[2] = toc->track[i].min; + rt[1] = toc->track[i].sec; + rt[0] = toc->track[i].frame; + } + //printf("%s %d -> %d:%02d:%02d\n", __func__, track, rt[2], rt[1], rt[0]); + return 0; +} + +static long CALLBACK rcdrom_prefetch(unsigned char m, unsigned char s, unsigned char f) +{ + unsigned int lba = cdrom_msf_to_lba(m, s, f) - 150; + if (rcdrom.cond && rcdrom.h) { + rcdrom.prefetch_lba = lba; + rcdrom.do_prefetch = 1; + scond_signal(rcdrom.cond); + } + if (rcdrom.buf) { + unsigned int c = rcdrom.buf_cnt; + if (c) + return rcdrom.buf[lba % c].lba == lba; + } + return 1; +} + +static int rcdrom_read_msf(unsigned char m, unsigned char s, unsigned char f, + void *buf, const char *func) +{ + unsigned int lba = cdrom_msf_to_lba(m, s, f) - 150; + int hit = 0, ret = -1; + if (rcdrom.buf_lock) + hit = lbacache_get(lba, buf); + if (!hit && rcdrom.read_lock) { + // maybe still prefetching + slock_lock(rcdrom.read_lock); + slock_unlock(rcdrom.read_lock); + hit = lbacache_get(lba, buf); + if (hit) + hit = 2; + } + if (!hit) { + slock_t *lock = rcdrom.read_lock; + rcdrom.do_prefetch = 0; + if (lock) + slock_lock(lock); + if (rcdrom.h) { + ret = cdrom_read_sector(rcdrom.h, lba, buf); + if (ret) + LogErr("cdrom_read_sector failed for lba %d\n", lba); + } + if (lock) + slock_unlock(lock); + } + else + ret = 0; + rcdrom.check_eject_delay = ret ? 0 : 100; + //printf("%s %d:%02d:%02d -> %d hit %d\n", func, m, s, f, ret, hit); + return ret; +} + +static boolean CALLBACK rcdrom_readTrack(unsigned char *time) +{ + unsigned char m = btoi(time[0]), s = btoi(time[1]), f = btoi(time[2]); + return !rcdrom_read_msf(m, s, f, ISOgetBuffer() - 12, __func__); +} + +static long CALLBACK rcdrom_readCDDA(unsigned char m, unsigned char s, unsigned char f, + unsigned char *buffer) +{ + return rcdrom_read_msf(m, s, f, buffer, __func__); +} + +static unsigned char * CALLBACK rcdrom_getBuffer(void) +{ + //printf("%s\n", __func__); + return ISOgetBuffer(); +} + +static unsigned char * CALLBACK rcdrom_getBufferSub(int sector) +{ + //printf("%s %d %d\n", __func__, sector, rcdrom_h->cdrom.last_frame_lba); + return NULL; +} + +static long CALLBACK rcdrom_getStatus(struct CdrStat *stat) +{ + const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc(); + //printf("%s %p\n", __func__, stat); + CDR__getStatus(stat); + stat->Type = toc->track[0].audio ? 2 : 1; + return 0; +} + +static void rcdrom_check_eject(void) +{ + bool media_inserted; + if (!rcdrom.h || rcdrom.do_prefetch || rcdrom.check_eject_delay-- > 0) + return; + rcdrom.check_eject_delay = 100; + media_inserted = cdrom_is_media_inserted(rcdrom.h); // 1-2ms + if (!media_inserted != disk_ejected) + disk_set_eject_state(!media_inserted); +} +#endif // HAVE_CDROM + #if defined(__QNX__) || defined(_WIN32) /* Blackberry QNX doesn't have strcasestr */ @@ -1675,7 +2008,7 @@ bool retro_load_game(const struct retro_game_info *info) if (info == NULL || info->path == NULL) { - SysPrintf("info->path required\n"); + LogErr("info->path required\n"); return false; } @@ -1695,7 +2028,7 @@ bool retro_load_game(const struct retro_game_info *info) { if (!read_m3u(info->path)) { - log_cb(RETRO_LOG_INFO, "failed to read m3u file\n"); + LogErr("failed to read m3u file\n"); return false; } } @@ -1728,16 +2061,36 @@ bool retro_load_game(const struct retro_game_info *info) /* have to reload after set_cd_image for correct cdr plugin */ if (LoadPlugins() == -1) { - log_cb(RETRO_LOG_INFO, "failed to load plugins\n"); + LogErr("failed to load plugins\n"); return false; } + if (!strncmp(info->path, "cdrom:", 6)) + { +#ifdef HAVE_CDROM + CDR_open = rcdrom_open; + CDR_close = rcdrom_close; + CDR_getTN = rcdrom_getTN; + CDR_getTD = rcdrom_getTD; + CDR_readTrack = rcdrom_readTrack; + CDR_getBuffer = rcdrom_getBuffer; + CDR_getBufferSub = rcdrom_getBufferSub; + CDR_getStatus = rcdrom_getStatus; + CDR_readCDDA = rcdrom_readCDDA; + CDR_prefetch = rcdrom_prefetch; +#elif !defined(USE_LIBRETRO_VFS) + ReleasePlugins(); + LogErr("%s\n", "Physical CD-ROM support is not compiled in."); + show_notification("Physical CD-ROM support is not compiled in.", 6000, 3); + return false; +#endif + } plugins_opened = 1; NetOpened = 0; if (OpenPlugins() == -1) { - log_cb(RETRO_LOG_INFO, "failed to open plugins\n"); + LogErr("failed to open plugins\n"); return false; } @@ -1796,12 +2149,12 @@ bool retro_load_game(const struct retro_game_info *info) if (ReloadCdromPlugin() < 0) { - log_cb(RETRO_LOG_INFO, "failed to reload cdr plugins\n"); + LogErr("failed to reload cdr plugins\n"); return false; } if (CDR_open() < 0) { - log_cb(RETRO_LOG_INFO, "failed to open cdr plugin\n"); + LogErr("failed to open cdr plugin\n"); return false; } } @@ -1816,7 +2169,7 @@ bool retro_load_game(const struct retro_game_info *info) if (!is_exe && CheckCdrom() == -1) { - log_cb(RETRO_LOG_INFO, "unsupported/invalid CD image: %s\n", info->path); + LogErr("unsupported/invalid CD image: %s\n", info->path); return false; } @@ -1828,7 +2181,7 @@ bool retro_load_game(const struct retro_game_info *info) ret = LoadCdrom(); if (ret != 0) { - log_cb(RETRO_LOG_INFO, "could not load %s (%d)\n", is_exe ? "exe" : "CD", ret); + LogErr("could not load %s (%d)\n", is_exe ? "exe" : "CD", ret); return false; } emu_on_new_cd(0); @@ -1912,6 +2265,7 @@ static void update_variables(bool in_flight) int gpu_peops_fix = GPU_PEOPS_OLD_FRAME_SKIP; #endif frameskip_type_t prev_frameskip_type; + double old_fps = psxGetFps(); var.value = NULL; var.key = "pcsx_rearmed_frameskip_type"; @@ -2011,6 +2365,30 @@ static void update_variables(bool in_flight) in_enable_vibration = 1; } + var.value = NULL; + var.key = "pcsx_rearmed_analog_combo"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "l1+r1+select") == 0) + in_dualshock_analog_combo = (1 << RETRO_DEVICE_ID_JOYPAD_L) | + (1 << RETRO_DEVICE_ID_JOYPAD_R) | (1 << RETRO_DEVICE_ID_JOYPAD_SELECT); + else if (strcmp(var.value, "l1+r1+start") == 0) + in_dualshock_analog_combo = (1 << RETRO_DEVICE_ID_JOYPAD_L) | + (1 << RETRO_DEVICE_ID_JOYPAD_R) | (1 << RETRO_DEVICE_ID_JOYPAD_START); + else if (strcmp(var.value, "l1+r1+l3") == 0) + in_dualshock_analog_combo = (1 << RETRO_DEVICE_ID_JOYPAD_L) | + (1 << RETRO_DEVICE_ID_JOYPAD_R) | (1 << RETRO_DEVICE_ID_JOYPAD_L3); + else if (strcmp(var.value, "l1+r1+r3") == 0) + in_dualshock_analog_combo = (1 << RETRO_DEVICE_ID_JOYPAD_L) | + (1 << RETRO_DEVICE_ID_JOYPAD_R) | (1 << RETRO_DEVICE_ID_JOYPAD_R3); + else if (strcmp(var.value, "l3+r3") == 0) + in_dualshock_analog_combo = (1 << RETRO_DEVICE_ID_JOYPAD_L3) | + (1 << RETRO_DEVICE_ID_JOYPAD_R3); + else + in_dualshock_analog_combo = 0; + } + var.value = NULL; var.key = "pcsx_rearmed_dithering"; @@ -2066,23 +2444,23 @@ static void update_variables(bool in_flight) 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) + if (strcmp(var.value, "enabled") == 0) pl_rearmed_cbs.gpu_neon.enhancement_no_main = 1; + else + pl_rearmed_cbs.gpu_neon.enhancement_no_main = 0; } -#endif var.value = NULL; - var.key = "pcsx_rearmed_duping_enable"; + var.key = "pcsx_rearmed_neon_enhancement_tex_adj"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - if (strcmp(var.value, "disabled") == 0) - duping_enable = false; - else if (strcmp(var.value, "enabled") == 0) - duping_enable = true; + if (strcmp(var.value, "enabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_tex_adj = 1; + else + pl_rearmed_cbs.gpu_neon.enhancement_tex_adj = 0; } +#endif var.value = NULL; var.key = "pcsx_rearmed_display_internal_fps"; @@ -2095,6 +2473,26 @@ static void update_variables(bool in_flight) display_internal_fps = true; } +#ifdef HAVE_CDROM + var.value = NULL; + var.key = "pcsx_rearmed_phys_cd_readahead"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + long newval = strtol(var.value, NULL, 10); + bool changed = rcdrom.buf_cnt != newval; + if (rcdrom.h && changed) + rcdrom_stop_thread(); + rcdrom.buf_cnt = newval; + if (rcdrom.h && changed) { + rcdrom_start_thread(); + if (rcdrom.cond && rcdrom.prefetch_lba) { + rcdrom.do_prefetch = 1; + scond_signal(rcdrom.cond); + } + } + } +#endif + // // CPU emulation related config #ifndef DRC_DISABLE @@ -2240,6 +2638,7 @@ static void update_variables(bool in_flight) spu_config.iUseInterpolation = 0; } +#if P_HAVE_PTHREAD var.value = NULL; var.key = "pcsx_rearmed_spu_thread"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -2249,7 +2648,9 @@ static void update_variables(bool in_flight) else spu_config.iUseThread = 0; } +#endif +#if 0 // currently disabled, see USE_READ_THREAD in libpcsxcore/cdriso.c if (P_HAVE_PTHREAD) { var.value = NULL; var.key = "pcsx_rearmed_async_cd"; @@ -2272,6 +2673,7 @@ static void update_variables(bool in_flight) } } } +#endif var.value = NULL; var.key = "pcsx_rearmed_noxadecoding"; @@ -2305,6 +2707,18 @@ static void update_variables(bool in_flight) Config.GpuListWalking = -1; } + var.value = NULL; + var.key = "pcsx_rearmed_fractional_framerate"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "disabled") == 0) + Config.FractionalFramerate = 0; + else if (strcmp(var.value, "enabled") == 0) + Config.FractionalFramerate = 1; + else // auto + Config.FractionalFramerate = -1; + } + var.value = NULL; var.key = "pcsx_rearmed_screen_centering"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -2573,6 +2987,18 @@ static void update_variables(bool in_flight) mouse_sensitivity = atof(var.value); } + if (found_bios) + { + var.value = NULL; + var.key = "pcsx_rearmed_show_bios_bootlogo"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + Config.SlowBoot = 0; + if (strcmp(var.value, "enabled") == 0) + Config.SlowBoot = 1; + } + } + if (in_flight) { // inform core things about possible config changes @@ -2590,29 +3016,15 @@ static void update_variables(bool in_flight) /* dfinput_activate(); */ } - else - { - //not yet running - - //bootlogo display hack - if (found_bios) - { - var.value = NULL; - var.key = "pcsx_rearmed_show_bios_bootlogo"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - Config.SlowBoot = 0; - rebootemu = 0; - if (strcmp(var.value, "enabled") == 0) - { - Config.SlowBoot = 1; - rebootemu = 1; - } - } - } - } update_option_visibility(); + + if (old_fps != psxGetFps()) + { + struct retro_system_av_info info; + retro_get_system_av_info(&info); + environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &info); + } } // Taken from beetle-psx-libretro @@ -2868,13 +3280,13 @@ static void update_input_mouse(int port, int ret) static void update_input(void) { - // reset all keystate, query libretro for keystate int i; int j; + // reset all keystate, query libretro for keystate for (i = 0; i < PORTS_NUMBER; i++) { - int16_t ret = 0; + int32_t ret = 0; int type = in_type[i]; in_keystate[i] = 0; @@ -2883,7 +3295,11 @@ static void update_input(void) continue; if (libretro_supports_bitmasks) + { ret = input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); + // undo int16 sign extension (why input_state_cb returns int16 in the first place?) + ret &= (1 << (RETRO_DEVICE_ID_JOYPAD_R3 + 1)) - 1; + } else { for (j = 0; j < (RETRO_DEVICE_ID_JOYPAD_R3 + 1); j++) @@ -2908,7 +3324,23 @@ static void update_input(void) update_input_mouse(i, ret); break; default: - // Query digital inputs + // dualshock ANALOG toggle? + if (type == PSE_PAD_TYPE_ANALOGPAD && in_dualshock_analog_combo != 0 + && ret == in_dualshock_analog_combo) + { + if (!in_dualshock_toggling) + { + int state = padToggleAnalog(i); + char msg[32]; + snprintf(msg, sizeof(msg), "ANALOG %s", state ? "ON" : "OFF"); + show_notification(msg, 800, 1); + in_dualshock_toggling = true; + } + return; + } + in_dualshock_toggling = false; + + // Set digital inputs for (j = 0; j < RETRO_PSX_MAP_LEN; j++) if (ret & (1 << j)) in_keystate[i] |= retro_psx_map[j]; @@ -3042,9 +3474,14 @@ void retro_run(void) frameskip_counter = 0; } - video_cb((vout_fb_dirty || !vout_can_dupe || !duping_enable) ? vout_buf_ptr : NULL, + video_cb((vout_fb_dirty || !vout_can_dupe) ? vout_buf_ptr : NULL, vout_width, vout_height, vout_pitch * 2); vout_fb_dirty = 0; + +#ifdef HAVE_CDROM + if (CDR_open == rcdrom_open) + rcdrom_check_eject(); +#endif } static bool try_use_bios(const char *path, bool preferred_only) @@ -3166,7 +3603,7 @@ static int init_memcards(void) { if (strlen(dir) + strlen(CARD2_FILE) + 2 > sizeof(Config.Mcd2)) { - SysPrintf("Path '%s' is too long. Cannot use memcard 2. Use a shorter path.\n", dir); + LogErr("Path '%s' is too long. Cannot use memcard 2. Use a shorter path.\n", dir); ret = -1; } else @@ -3178,7 +3615,7 @@ static int init_memcards(void) } else { - SysPrintf("Could not get save directory! Could not create memcard 2."); + LogErr("Could not get save directory! Could not create memcard 2."); ret = -1; } } @@ -3293,7 +3730,7 @@ void retro_init(void) ret |= emu_core_init(); if (ret != 0) { - SysPrintf("PCSX init failed.\n"); + LogErr("PCSX init failed.\n"); exit(1); } @@ -3313,6 +3750,8 @@ void retro_init(void) loadPSXBios(); environ_cb(RETRO_ENVIRONMENT_GET_CAN_DUPE, &vout_can_dupe); + if (!vout_can_dupe) + LogWarn("CAN_DUPE reports false\n"); disk_initial_index = 0; disk_initial_path[0] = '\0';