#include <sys/syscall.h>
#endif
+#include "retro_miscellaneous.h"
#ifdef SWITCH
#include <switch.h>
#endif
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;
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;
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
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
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);
}
#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;
}
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);
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);
}
}
+#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;
}
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,
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;
}
}
+// 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 */
if (info == NULL || info->path == NULL)
{
- SysPrintf("info->path required\n");
+ LogErr("info->path required\n");
return false;
}
{
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;
}
}
/* 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;
}
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;
}
}
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;
}
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);
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";
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";
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
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)
else
spu_config.iUseThread = 0;
}
+#endif
#if 0 // currently disabled, see USE_READ_THREAD in libpcsxcore/cdriso.c
if (P_HAVE_PTHREAD) {
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;
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++)
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];
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)
{
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
}
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;
}
}
ret |= emu_core_init();
if (ret != 0)
{
- SysPrintf("PCSX init failed.\n");
+ LogErr("PCSX init failed.\n");
exit(1);
}
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';