Should've split this really, but that's lots of extra work...
Beware of breakage, but please report bugs.
endif
# core
-OBJS += libpcsxcore/cdriso.o libpcsxcore/cdrom.o libpcsxcore/cheat.o libpcsxcore/database.o \
+OBJS += libpcsxcore/cdriso.o libpcsxcore/cdrom.o libpcsxcore/cdrom-async.o \
+ libpcsxcore/cheat.o libpcsxcore/database.o \
libpcsxcore/decode_xa.o libpcsxcore/mdec.o \
libpcsxcore/misc.o libpcsxcore/plugins.o libpcsxcore/ppf.o libpcsxcore/psxbios.o \
libpcsxcore/psxcommon.o libpcsxcore/psxcounters.o libpcsxcore/psxdma.o \
CC_LINK = $(CXX)
endif
-# cdrcimg
-OBJS += plugins/cdrcimg/cdrcimg.o
-
# libchdr
ifeq "$(HAVE_CHD)" "1"
LCHDR = deps/libchdr
OBJS += frontend/libretro-cdrom.o
OBJS += deps/libretro-common/lists/string_list.o
OBJS += deps/libretro-common/memmap/memalign.o
-OBJS += deps/libretro-common/rthreads/rthreads.o
OBJS += deps/libretro-common/vfs/vfs_implementation_cdrom.o
CFLAGS += -DHAVE_CDROM
endif
+ifeq "$(USE_ASYNC_CDROM)" "1"
+OBJS += frontend/libretro-rthreads.o
+CFLAGS += -DUSE_ASYNC_CDROM
+endif
ifeq "$(USE_LIBRETRO_VFS)" "1"
OBJS += deps/libretro-common/compat/compat_posix_string.o
OBJS += deps/libretro-common/compat/fopen_utf8.o
WANT_ZLIB ?= 1
HAVE_CHD ?= 1
HAVE_PHYSICAL_CDROM ?= 1
+USE_ASYNC_CDROM ?= 1
USE_LIBRETRO_VFS ?= 0
# Dynarec options: lightrec, ari64
--- /dev/null
+// temporary(?) workaround:
+// https://github.com/libretro/libretro-common/pull/216
+#ifdef _3DS
+#include <3ds/svc.h>
+#include <3ds/services/apt.h>
+#include <sys/time.h>
+#endif
+
+#include "../deps/libretro-common/rthreads/rthreads.c"
#include "../libpcsxcore/psxmem_map.h"
#include "../libpcsxcore/new_dynarec/new_dynarec.h"
#include "../libpcsxcore/cdrom.h"
+#include "../libpcsxcore/cdrom-async.h"
#include "../libpcsxcore/cdriso.h"
#include "../libpcsxcore/cheat.h"
#include "../libpcsxcore/r3000a.h"
}
}
-#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)
{
if (ejected != disk_ejected)
LidInterrupt();
#ifdef HAVE_CDROM
- if (CDR_open == rcdrom_open && ejected != disk_ejected) {
- rcdrom_stop_thread();
+ if (cdra_is_physical() && ejected != disk_ejected) {
+ cdra_stop_thread();
if (!ejected) {
// likely the real cd was also changed - rescan
- rcdrom_close();
- rcdrom_open();
+ cdra_close();
+ cdra_open();
}
}
#endif
if (disks[index].fname == NULL)
{
LogErr("missing disk #%u\n", index);
- CDR_shutdown();
+ cdra_shutdown();
// RetroArch specifies "no disk" with index == count,
// so don't fail here..
LogErr("failed to load cdr plugin\n");
return false;
}
- if (CDR_open() < 0)
+ if (cdra_open() < 0)
{
LogErr("failed to open cdr plugin\n");
return false;
}
}
-// 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 (!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)
+#if !defined(HAVE_CDROM) && !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);
LogErr("failed to reload cdr plugins\n");
return false;
}
- if (CDR_open() < 0)
+ if (cdra_open() < 0)
{
LogErr("failed to open cdr plugin\n");
return false;
Config.TurboCD = false;
}
-#ifdef HAVE_CDROM
+#if defined(HAVE_CDROM) || defined(USE_ASYNC_CDROM)
var.value = NULL;
- var.key = "pcsx_rearmed_phys_cd_readahead";
+ var.key = "pcsx_rearmed_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);
- }
- }
+ cdra_set_buf_count(strtol(var.value, NULL, 10));
}
#endif
vout_fb_dirty = 0;
#ifdef HAVE_CDROM
- if (CDR_open == rcdrom_open)
- rcdrom_check_eject();
+ int inserted;
+ if (cdra_check_eject(&inserted) > 0) {
+ bool media_inserted = inserted != 0;
+ if (!media_inserted != disk_ejected)
+ disk_set_eject_state(!media_inserted);
+ }
#endif
}
"sync",
},
#endif
-#ifdef HAVE_CDROM
+#if defined(HAVE_CDROM) || defined(USE_ASYNC_CDROM)
#define V(x) { #x, NULL }
{
- "pcsx_rearmed_phys_cd_readahead",
- "Physical CD read-ahead",
+ "pcsx_rearmed_cd_readahead",
+ "CD read-ahead",
NULL,
- "(Hardware CD-ROM only) Reads the specified amount of sectors ahead of time to try to avoid later stalls. 333000 will try to read the complete disk (requires an additional 750MB of RAM).",
+ "Reads the specified amount of sectors ahead of time to try to avoid later stalls. "
+#ifdef HAVE_CDROM
+ "Affects both physical CD-ROM and CD images. "
+#endif
+#if !defined(_3DS) && !defined(VITA)
+ "333000 will try to read the complete disk (requires an additional 750MB of RAM)."
+#endif
+ ,
NULL,
"system",
{
V(0), V(1), V(2), V(3), V(4), V(5), V(6), V(7),
V(8), V(9), V(10), V(11), V(12), V(13), V(14), V(15),
- V(16), V(32), V(64), V(128), V(256), V(512), V(1024), V(333000),
+ V(16), V(32), V(64), V(128), V(256), V(512), V(1024),
+#if !defined(_3DS) && !defined(VITA)
+ V(333000),
+#endif
{ NULL, NULL},
},
"12",
#include "../libpcsxcore/cheat.h"
#include "../libpcsxcore/sio.h"
#include "../libpcsxcore/database.h"
+#include "../libpcsxcore/cdrom-async.h"
#include "../libpcsxcore/new_dynarec/new_dynarec.h"
#include "../plugins/cdrcimg/cdrcimg.h"
#include "../plugins/dfsound/spu_config.h"
char hud_msg[64];
int hud_new_msg;
-static void make_path(char *buf, size_t size, const char *dir, const char *fname)
+static inline void make_path(char *buf, size_t size, const char *dir, const char *fname)
{
if (fname)
snprintf(buf, size, ".%s%s", dir, fname);
void set_cd_image(const char *fname)
{
- const char *ext = NULL;
-
- if (fname != NULL)
- ext = strrchr(fname, '.');
-
- if (ext && (
- strcasecmp(ext, ".z") == 0 || strcasecmp(ext, ".bz") == 0 ||
- strcasecmp(ext, ".znx") == 0 /*|| strcasecmp(ext, ".pbp") == 0*/)) {
- SetIsoFile(NULL);
- cdrcimg_set_fname(fname);
- strcpy(Config.Cdr, "builtin_cdrcimg");
- } else {
- SetIsoFile(fname);
- strcpy(Config.Cdr, "builtin_cdr");
- }
+ SetIsoFile(fname);
}
static void set_default_paths(void)
strcpy(Config.PluginsDir, "plugins");
strcpy(Config.Gpu, "builtin_gpu");
strcpy(Config.Spu, "builtin_spu");
- strcpy(Config.Cdr, "builtin_cdr");
strcpy(Config.Pad1, "builtin_pad");
strcpy(Config.Pad2, "builtin_pad");
strcpy(Config.Net, "Disabled");
// reset can run code, timing must be set
pl_timing_prepare(Config.PsxType);
- // hmh core forgets this
- CDR_stop();
-
EmuReset();
GPU_updateLace = real_lace;
signal(SIGPIPE, SignalExit);
#endif
- ret = CDR_open();
+ ret = cdra_open();
if (ret < 0) { SysMessage(_("Error opening CD-ROM plugin!")); return -1; }
ret = SPU_open();
if (ret < 0) { SysMessage(_("Error opening SPU plugin!")); return -1; }
ret = PAD2_open(&gpuDisp);
if (ret < 0) { SysMessage(_("Error opening Controller 2 plugin!")); return -1; }
- if (Config.UseNet && !NetOpened) {
- netInfo info;
- char path[MAXPATHLEN * 2];
- char dotdir[MAXPATHLEN];
-
- MAKE_PATH(dotdir, "/.pcsx/plugins/", NULL);
-
- strcpy(info.EmuName, "PCSX");
- memcpy(info.CdromID, CdromId, 9); /* no \0 trailing character? */
- memcpy(info.CdromLabel, CdromLabel, 9);
- info.CdromLabel[9] = '\0';
- info.psxMem = psxM;
- info.GPU_showScreenPic = GPU_showScreenPic;
- info.GPU_displayText = GPU_displayText;
- info.GPU_showScreenPic = GPU_showScreenPic;
- info.PAD_setSensitive = PAD1_setSensitive;
- sprintf(path, "%s%s", Config.BiosDir, Config.Bios);
- strcpy(info.BIOSpath, path);
- strcpy(info.MCD1path, Config.Mcd1);
- strcpy(info.MCD2path, Config.Mcd2);
- sprintf(path, "%s%s", dotdir, Config.Gpu);
- strcpy(info.GPUpath, path);
- sprintf(path, "%s%s", dotdir, Config.Spu);
- strcpy(info.SPUpath, path);
- sprintf(path, "%s%s", dotdir, Config.Cdr);
- strcpy(info.CDRpath, path);
- NET_setInfo(&info);
-
- ret = NET_open(&gpuDisp);
- if (ret < 0) {
- if (ret == -2) {
- // -2 is returned when something in the info
- // changed and needs to be synced
- char *ptr;
-
- PARSEPATH(Config.Bios, info.BIOSpath);
- PARSEPATH(Config.Gpu, info.GPUpath);
- PARSEPATH(Config.Spu, info.SPUpath);
- PARSEPATH(Config.Cdr, info.CDRpath);
-
- strcpy(Config.Mcd1, info.MCD1path);
- strcpy(Config.Mcd2, info.MCD2path);
- return -2;
- } else {
- Config.UseNet = FALSE;
- }
- } else {
- if (NET_queryPlayer() == 1) {
- if (SendPcsxInfo() == -1) Config.UseNet = FALSE;
- } else {
- if (RecvPcsxInfo() == -1) Config.UseNet = FALSE;
- }
- }
- NetOpened = TRUE;
- } else if (Config.UseNet) {
- NET_resume();
- }
-
return 0;
}
signal(SIGPIPE, SIG_DFL);
#endif
- ret = CDR_close();
- if (ret < 0) { SysMessage(_("Error closing CD-ROM plugin!")); return; }
+ cdra_close();
ret = SPU_close();
- if (ret < 0) { SysMessage(_("Error closing SPU plugin!")); return; }
+ if (ret < 0) { SysMessage(_("Error closing SPU plugin!")); }
ret = PAD1_close();
- if (ret < 0) { SysMessage(_("Error closing Controller 1 Plugin!")); return; }
+ if (ret < 0) { SysMessage(_("Error closing Controller 1 Plugin!")); }
ret = PAD2_close();
- if (ret < 0) { SysMessage(_("Error closing Controller 2 plugin!")); return; }
+ if (ret < 0) { SysMessage(_("Error closing Controller 2 plugin!")); }
// pcsx-rearmed: we handle gpu elsewhere
//ret = GPU_close();
//if (ret < 0) { SysMessage(_("Error closing GPU plugin!")); return; }
-
- if (Config.UseNet) {
- NET_pause();
- }
}
/* we hook statically linked plugins here */
static const char *builtin_plugins[] = {
- "builtin_gpu", "builtin_spu", "builtin_cdr", "builtin_pad",
- "builtin_cdrcimg",
+ "builtin_gpu", "builtin_spu", "builtin_pad",
};
static const int builtin_plugin_ids[] = {
- PLUGIN_GPU, PLUGIN_SPU, PLUGIN_CDR, PLUGIN_PAD,
- PLUGIN_CDRCIMG,
+ PLUGIN_GPU, PLUGIN_SPU, PLUGIN_PAD,
};
void *SysLoadLibrary(const char *lib) {
#include "libpicofe/plat.h"
#include "../libpcsxcore/misc.h"
#include "../libpcsxcore/cdrom.h"
+#include "../libpcsxcore/cdrom-async.h"
#include "../libpcsxcore/cdriso.h"
#include "../libpcsxcore/cheat.h"
#include "../libpcsxcore/ppf.h"
menu_update_msg("failed to load cdr plugin");
return -1;
}
- if (CDR_open() < 0) {
+ if (cdra_open() < 0) {
menu_update_msg("failed to open cdr plugin");
return -1;
}
CdromId[0] = '\0';
CdromLabel[0] = '\0';
- CDR_close();
- if (CDR_open() < 0) {
+ cdra_close();
+ if (cdra_open() < 0) {
menu_update_msg("failed to open cdr plugin");
return -1;
}
menu_sync_config();
psxCpu->ApplyConfig();
- // core doesn't care about Config.Cdda changes,
- // so handle them manually here
- if (Config.Cdda)
- CDR_stop();
-
if (cpu_clock > 0)
plat_target_cpu_clock_set(cpu_clock);
#undef CALLBACK
#define CALLBACK
-/* CDR */
-struct CdrStat;
-static long CALLBACK CDRinit(void) { return 0; }
-static long CALLBACK CDRshutdown(void) { return 0; }
-static long CALLBACK CDRopen(void) { return 0; }
-static long CALLBACK CDRclose(void) { return 0; }
-static long CALLBACK CDRgetTN(unsigned char *_) { return 0; }
-static long CALLBACK CDRgetTD(unsigned char _, unsigned char *__) { return 0; }
-static boolean CALLBACK CDRreadTrack(unsigned char *_) { return FALSE; }
-static unsigned char * CALLBACK CDRgetBuffer(void) { return NULL; }
-static unsigned char * CALLBACK CDRgetBufferSub(int sector) { return NULL; }
-static long CALLBACK CDRconfigure(void) { return 0; }
-static long CALLBACK CDRtest(void) { return 0; }
-static void CALLBACK CDRabout(void) { return; }
-static long CALLBACK CDRplay(unsigned char *_) { return 0; }
-static long CALLBACK CDRstop(void) { return 0; }
-static long CALLBACK CDRsetfilename(char *_) { return 0; }
-static long CALLBACK CDRgetStatus(struct CdrStat *_) { return 0; }
-static char * CALLBACK CDRgetDriveLetter(void) { return NULL; }
-static long CALLBACK CDRreadCDDA(unsigned char _, unsigned char __, unsigned char ___, unsigned char *____) { return 0; }
-static long CALLBACK CDRgetTE(unsigned char _, unsigned char *__, unsigned char *___, unsigned char *____) { return 0; }
-static long CALLBACK CDRprefetch(unsigned char m, unsigned char s, unsigned char f) { return 1; }
-
/* GPU */
static void CALLBACK GPUdisplayText(char *_) { return; }
#define DIRECT(id, name) \
{ id, #name, name }
-#define DIRECT_CDR(name) DIRECT(PLUGIN_CDR, name)
#define DIRECT_SPU(name) DIRECT(PLUGIN_SPU, name)
#define DIRECT_GPU(name) DIRECT(PLUGIN_GPU, name)
#define DIRECT_PAD(name) DIRECT(PLUGIN_PAD, name)
const char *name;
void *func;
} plugin_funcs[] = {
- /* CDR */
- DIRECT_CDR(CDRinit),
- DIRECT_CDR(CDRshutdown),
- DIRECT_CDR(CDRopen),
- DIRECT_CDR(CDRclose),
- DIRECT_CDR(CDRtest),
- DIRECT_CDR(CDRgetTN),
- DIRECT_CDR(CDRgetTD),
- DIRECT_CDR(CDRreadTrack),
- DIRECT_CDR(CDRgetBuffer),
- DIRECT_CDR(CDRgetBufferSub),
- DIRECT_CDR(CDRplay),
- DIRECT_CDR(CDRstop),
- DIRECT_CDR(CDRgetStatus),
- DIRECT_CDR(CDRgetDriveLetter),
- DIRECT_CDR(CDRconfigure),
- DIRECT_CDR(CDRabout),
- DIRECT_CDR(CDRsetfilename),
- DIRECT_CDR(CDRreadCDDA),
- DIRECT_CDR(CDRgetTE),
- DIRECT_CDR(CDRprefetch),
/* SPU */
DIRECT_SPU(SPUinit),
DIRECT_SPU(SPUshutdown),
{
int i;
- if (id == PLUGIN_CDRCIMG)
- return cdrcimg_get_sym(sym);
-
for (i = 0; i < ARRAY_SIZE(plugin_funcs); i++) {
if (id != plugin_funcs[i].id)
continue;
enum builtint_plugins_e {
PLUGIN_GPU,
PLUGIN_SPU,
- PLUGIN_CDR,
PLUGIN_PAD,
- PLUGIN_CDRCIMG,
};
void *plugin_link(enum builtint_plugins_e id, const char *sym);
$(shell cd "$(LOCAL_PATH)" && (rm ../frontend/revision.h_))
USE_LIBRETRO_VFS ?= 0
+USE_ASYNC_CDROM ?= 1
ROOT_DIR := $(LOCAL_PATH)/..
CORE_DIR := $(ROOT_DIR)/libpcsxcore
# core
SOURCES_C := $(CORE_DIR)/cdriso.c \
$(CORE_DIR)/cdrom.c \
+ $(CORE_DIR)/cdrom-async.c \
$(CORE_DIR)/cheat.c \
$(CORE_DIR)/database.c \
$(CORE_DIR)/decode_xa.c \
$(LIBRETRO_COMMON)/vfs/vfs_implementation.c
COREFLAGS += -DUSE_LIBRETRO_VFS
endif
+ifeq ($(USE_ASYNC_CDROM),1)
+SOURCES_C += \
+ $(FRONTEND_DIR)/libretro-rthreads.c
+COREFLAGS += -DUSE_ASYNC_CDROM
+endif
EXTRA_INCLUDES += $(LIBRETRO_COMMON)/include
HAVE_ARI64=0
***************************************************************************/
#include "psxcommon.h"
-#include "plugins.h"
#include "cdrom.h"
#include "cdriso.h"
#include "ppf.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#if P_HAVE_PTHREAD
-#include <pthread.h>
-#include <sys/time.h>
#endif
-#endif
-
-// to enable the USE_READ_THREAD code, fix:
-// - https://github.com/notaz/pcsx_rearmed/issues/257
-// - ISOgetBufferSub to not race with async code
-#define USE_READ_THREAD 0 //P_HAVE_PTHREAD
#ifdef USE_LIBRETRO_VFS
#include <streams/file_stream_transforms.h>
static boolean multifile = FALSE;
static unsigned char cdbuffer[CD_FRAMESIZE_RAW];
-static unsigned char subbuffer[SUB_FRAMESIZE];
static boolean cddaBigEndian = FALSE;
/* Frame offset into CD image where pregap data would be found if it was there.
#endif
static int (*cdimg_read_func)(FILE *f, unsigned int base, void *dest, int sector);
-static int (*cdimg_read_sub_func)(FILE *f, int sector);
-
-char* CALLBACK CDR__getDriveLetter(void);
-long CALLBACK CDR__configure(void);
-long CALLBACK CDR__test(void);
-void CALLBACK CDR__about(void);
-long CALLBACK CDR__setfilename(char *filename);
-long CALLBACK CDR__prefetch(u8 m, u8 s, u8 f);
+static int (*cdimg_read_sub_func)(FILE *f, int sector, void *dest);
-static void DecodeRawSubData(void);
+static void DecodeRawSubData(unsigned char *subbuffer);
struct trackinfo {
enum {DATA=1, CDDA} type;
static struct trackinfo ti[MAXTRACKS];
// get a sector from a msf-array
-static unsigned int msf2sec(char *msf) {
+static unsigned int msf2sec(const void *msf_) {
+ const unsigned char *msf = msf_;
return ((msf[0] * 60 + msf[1]) * 75) + msf[2];
}
-static void sec2msf(unsigned int s, char *msf) {
+static void sec2msf(unsigned int s, void *msf_) {
+ unsigned char *msf = msf_;
msf[0] = s / 75 / 60;
s = s - msf[0] * 75 * 60;
msf[1] = s / 75;
return LoadSBI(sbiname, s);
}
-#if !USE_READ_THREAD
-static void readThreadStop() {}
-static void readThreadStart() {}
-#else
-static pthread_t read_thread_id;
-
-static pthread_cond_t read_thread_msg_avail;
-static pthread_cond_t read_thread_msg_done;
-static pthread_mutex_t read_thread_msg_lock;
-
-static pthread_cond_t sectorbuffer_cond;
-static pthread_mutex_t sectorbuffer_lock;
-
-static boolean read_thread_running = FALSE;
-static int read_thread_sector_start = -1;
-static int read_thread_sector_end = -1;
-
-typedef struct {
- int sector;
- long ret;
- unsigned char data[CD_FRAMESIZE_RAW];
-} SectorBufferEntry;
-
-#define SECTOR_BUFFER_SIZE 4096
-
-static SectorBufferEntry *sectorbuffer;
-static size_t sectorbuffer_index;
-
-int (*sync_cdimg_read_func)(FILE *f, unsigned int base, void *dest, int sector);
-unsigned char *(*sync_CDR_getBuffer)(void);
-
-static unsigned char * CALLBACK ISOgetBuffer_async(void);
-static int cdread_async(FILE *f, unsigned int base, void *dest, int sector);
-
-static void *readThreadMain(void *param) {
- int max_sector = -1;
- int requested_sector_start = -1;
- int requested_sector_end = -1;
- int last_read_sector = -1;
- int index = 0;
-
- int ra_sector = -1;
- int max_ra = 128;
- int initial_ra = 1;
- int speedmult_ra = 4;
-
- int ra_count = 0;
- int how_far_ahead = 0;
-
- unsigned char tmpdata[CD_FRAMESIZE_RAW];
- long ret;
-
- max_sector = msf2sec(ti[numtracks].start) + msf2sec(ti[numtracks].length);
-
- while(1) {
- pthread_mutex_lock(&read_thread_msg_lock);
-
- // If we don't have readahead and we don't have a sector request, wait for one.
- // If we still have readahead to go, don't block, just keep going.
- // And if we ever have a sector request pending, acknowledge and reset it.
-
- if (!ra_count) {
- if (read_thread_sector_start == -1 && read_thread_running) {
- pthread_cond_wait(&read_thread_msg_avail, &read_thread_msg_lock);
- }
- }
-
- if (read_thread_sector_start != -1) {
- requested_sector_start = read_thread_sector_start;
- requested_sector_end = read_thread_sector_end;
- read_thread_sector_start = -1;
- read_thread_sector_end = -1;
- pthread_cond_signal(&read_thread_msg_done);
- }
-
- pthread_mutex_unlock(&read_thread_msg_lock);
-
- if (!read_thread_running)
- break;
-
- // Readahead code, based on the implementation in mednafen psx's cdromif.cpp
- if (requested_sector_start != -1) {
- if (last_read_sector != -1 && last_read_sector == (requested_sector_start - 1)) {
- how_far_ahead = ra_sector - requested_sector_end;
-
- if(how_far_ahead <= max_ra)
- ra_count = (max_ra - how_far_ahead + 1 ? max_ra - how_far_ahead + 1 : speedmult_ra);
- else
- ra_count++;
- } else if (requested_sector_end != last_read_sector) {
- ra_sector = requested_sector_end;
- ra_count = initial_ra;
- }
-
- last_read_sector = requested_sector_end;
- }
-
- index = ra_sector % SECTOR_BUFFER_SIZE;
-
- // check for end of CD
- if (ra_count && ra_sector >= max_sector) {
- ra_count = 0;
- pthread_mutex_lock(§orbuffer_lock);
- sectorbuffer[index].ret = -1;
- sectorbuffer[index].sector = ra_sector;
- pthread_cond_signal(§orbuffer_cond);
- pthread_mutex_unlock(§orbuffer_lock);
- }
-
- if (ra_count) {
- pthread_mutex_lock(§orbuffer_lock);
- if (sectorbuffer[index].sector != ra_sector) {
- pthread_mutex_unlock(§orbuffer_lock);
-
- ret = sync_cdimg_read_func(cdHandle, 0, tmpdata, ra_sector);
-
- pthread_mutex_lock(§orbuffer_lock);
- sectorbuffer[index].ret = ret;
- sectorbuffer[index].sector = ra_sector;
- memcpy(sectorbuffer[index].data, tmpdata, CD_FRAMESIZE_RAW);
- }
- pthread_cond_signal(§orbuffer_cond);
- pthread_mutex_unlock(§orbuffer_lock);
-
- ra_sector++;
- ra_count--;
- }
- }
-
- return NULL;
-}
-
-static void readThreadStop() {
- if (read_thread_running == TRUE) {
- read_thread_running = FALSE;
- pthread_cond_signal(&read_thread_msg_avail);
- pthread_join(read_thread_id, NULL);
- }
-
- pthread_cond_destroy(&read_thread_msg_done);
- pthread_cond_destroy(&read_thread_msg_avail);
- pthread_mutex_destroy(&read_thread_msg_lock);
-
- pthread_cond_destroy(§orbuffer_cond);
- pthread_mutex_destroy(§orbuffer_lock);
-
- CDR_getBuffer = sync_CDR_getBuffer;
- cdimg_read_func = sync_cdimg_read_func;
-
- free(sectorbuffer);
- sectorbuffer = NULL;
-}
-
-static void readThreadStart() {
- SysPrintf("Starting async CD thread\n");
-
- if (read_thread_running == TRUE)
- return;
-
- read_thread_running = TRUE;
- read_thread_sector_start = -1;
- read_thread_sector_end = -1;
- sectorbuffer_index = 0;
-
- sectorbuffer = calloc(SECTOR_BUFFER_SIZE, sizeof(SectorBufferEntry));
- if(!sectorbuffer)
- goto error;
-
- sectorbuffer[0].sector = -1; // Otherwise we might think we've already fetched sector 0!
-
- sync_CDR_getBuffer = CDR_getBuffer;
- CDR_getBuffer = ISOgetBuffer_async;
- sync_cdimg_read_func = cdimg_read_func;
- cdimg_read_func = cdread_async;
-
- if (pthread_cond_init(&read_thread_msg_avail, NULL) ||
- pthread_cond_init(&read_thread_msg_done, NULL) ||
- pthread_mutex_init(&read_thread_msg_lock, NULL) ||
- pthread_cond_init(§orbuffer_cond, NULL) ||
- pthread_mutex_init(§orbuffer_lock, NULL) ||
- pthread_create(&read_thread_id, NULL, readThreadMain, NULL))
- goto error;
-
- return;
-
- error:
- SysPrintf("Error starting async CD thread\n");
- SysPrintf("Falling back to sync\n");
-
- readThreadStop();
-}
-#endif
-
static int cdread_normal(FILE *f, unsigned int base, void *dest, int sector)
{
int ret;
if (!f)
return -1;
+ if (!dest)
+ dest = cdbuffer;
if (fseeko(f, base + sector * CD_FRAMESIZE_RAW, SEEK_SET))
goto fail_io;
ret = fread(dest, 1, CD_FRAMESIZE_RAW, f);
if (!f)
return -1;
+ if (!dest)
+ dest = cdbuffer;
if (fseeko(f, base + sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET))
goto fail_io;
ret = fread(dest, 1, CD_FRAMESIZE_RAW, f);
return -1;
}
-static int cdread_sub_sub_mixed(FILE *f, int sector)
+static int cdread_sub_sub_mixed(FILE *f, int sector, void *buffer)
{
if (!f)
return -1;
if (fseeko(f, sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE) + CD_FRAMESIZE_RAW, SEEK_SET))
goto fail_io;
- if (fread(subbuffer, 1, SUB_FRAMESIZE, f) != SUB_FRAMESIZE)
+ if (fread(buffer, 1, SUB_FRAMESIZE, f) != SUB_FRAMESIZE)
goto fail_io;
- return SUB_FRAMESIZE;
+ return 0;
fail_io:
SysPrintf("subchannel: file IO error %d, sector %u\n", errno, sector);
if (fread(is_compressed ? compr_img->buff_compressed : compr_img->buff_raw[0],
1, size, cdHandle) != size) {
- SysPrintf("read error for block %d at %x: ", block, start_byte);
+ SysPrintf("read error for block %d at %zx: ", block, start_byte);
perror(NULL);
return -1;
}
compr_img->current_block = block;
finish:
- if (dest != cdbuffer) // copy avoid HACK
+ if (dest != NULL)
memcpy(dest, compr_img->buff_raw[compr_img->sector_in_blk],
CD_FRAMESIZE_RAW);
return CD_FRAMESIZE_RAW;
chd_img->current_hunk[chd_img->current_buffer] = hunk;
}
- if (dest != cdbuffer) // copy avoid HACK
+ if (dest != NULL)
memcpy(dest, chd_get_sector(chd_img->current_buffer, chd_img->sector_in_hunk),
CD_FRAMESIZE_RAW);
return CD_FRAMESIZE_RAW;
}
-static int cdread_sub_chd(FILE *f, int sector)
+static int cdread_sub_chd(FILE *f, int sector, void *buffer_ptr)
{
unsigned int sector_in_hunk;
unsigned int buffer;
chd_img->current_hunk[buffer] = hunk;
}
- memcpy(subbuffer, chd_get_sector(buffer, sector_in_hunk) + CD_FRAMESIZE_RAW, SUB_FRAMESIZE);
- return SUB_FRAMESIZE;
+ memcpy(buffer_ptr, chd_get_sector(buffer, sector_in_hunk) + CD_FRAMESIZE_RAW, SUB_FRAMESIZE);
+ return 0;
}
#endif
static int cdread_2048(FILE *f, unsigned int base, void *dest, int sector)
{
+ unsigned char *dst = dest ? dest : cdbuffer;
int ret;
if (!f)
return -1;
+
fseeko(f, base + sector * 2048, SEEK_SET);
- ret = fread((char *)dest + 12 * 2, 1, 2048, f);
+ ret = fread(dst + 12 * 2, 1, 2048, f);
// not really necessary, fake mode 2 header
- memset(cdbuffer, 0, 12 * 2);
- sec2msf(sector + 2 * 75, (char *)&cdbuffer[12]);
- cdbuffer[12 + 3] = 1;
+ memset(dst, 0, 12 * 2);
+ sec2msf(sector + 2 * 75, dst + 12);
+ dst[12 + 0] = itob(dst[12 + 0]);
+ dst[12 + 1] = itob(dst[12 + 1]);
+ dst[12 + 2] = itob(dst[12 + 2]);
+ dst[12 + 3] = 1;
return 12*2 + ret;
}
-#if USE_READ_THREAD
-
-static int cdread_async(FILE *f, unsigned int base, void *dest, int sector) {
- boolean found = FALSE;
- int i = sector % SECTOR_BUFFER_SIZE;
- long ret;
-
- if (f != cdHandle || base != 0 || dest != cdbuffer) {
- // Async reads are only supported for cdbuffer, so call the sync
- // function directly.
- return sync_cdimg_read_func(f, base, dest, sector);
- }
-
- pthread_mutex_lock(&read_thread_msg_lock);
-
- // Only wait if we're not trying to read the next sector and
- // sector_start is set (meaning the last request hasn't been
- // processed yet)
- while(read_thread_sector_start != -1 && read_thread_sector_end + 1 != sector) {
- pthread_cond_wait(&read_thread_msg_done, &read_thread_msg_lock);
- }
-
- if (read_thread_sector_start == -1)
- read_thread_sector_start = sector;
-
- read_thread_sector_end = sector;
- pthread_cond_signal(&read_thread_msg_avail);
- pthread_mutex_unlock(&read_thread_msg_lock);
-
- do {
- pthread_mutex_lock(§orbuffer_lock);
- if (sectorbuffer[i].sector == sector) {
- sectorbuffer_index = i;
- ret = sectorbuffer[i].ret;
- found = TRUE;
- }
-
- if (!found) {
- pthread_cond_wait(§orbuffer_cond, §orbuffer_lock);
- }
- pthread_mutex_unlock(§orbuffer_lock);
- } while (!found);
-
- return ret;
+static void * ISOgetBuffer_normal(void) {
+ return cdbuffer + 12;
}
-#endif
-
-static unsigned char * CALLBACK ISOgetBuffer_compr(void) {
- return compr_img->buff_raw[compr_img->sector_in_blk] + 12;
+static void * ISOgetBuffer_compr(void) {
+ return compr_img->buff_raw[compr_img->sector_in_blk] + 12;
}
#ifdef HAVE_CHD
-static unsigned char * CALLBACK ISOgetBuffer_chd(void) {
- return chd_get_sector(chd_img->current_buffer, chd_img->sector_in_hunk) + 12;
+static void * ISOgetBuffer_chd(void) {
+ return chd_get_sector(chd_img->current_buffer, chd_img->sector_in_hunk) + 12;
}
#endif
-#if USE_READ_THREAD
-static unsigned char * CALLBACK ISOgetBuffer_async(void) {
- unsigned char *buffer;
- pthread_mutex_lock(§orbuffer_lock);
- buffer = sectorbuffer[sectorbuffer_index].data;
- pthread_mutex_unlock(§orbuffer_lock);
- return buffer + 12;
-}
-#endif
-
-unsigned char * CALLBACK ISOgetBuffer(void) {
- return cdbuffer + 12;
-}
+void * (*ISOgetBuffer)(void) = ISOgetBuffer_normal;
static void PrintTracks(void) {
int i;
// This function is invoked by the front-end when opening an ISO
// file for playback
-static long CALLBACK ISOopen(void) {
+int ISOopen(const char *fname)
+{
boolean isMode1ISO = FALSE;
char alt_bin_filename[MAXPATHLEN];
const char *bin_filename;
return 0; // it's already open
}
- cdHandle = fopen(GetIsoFile(), "rb");
+ cdHandle = fopen(fname, "rb");
if (cdHandle == NULL) {
SysPrintf(_("Could't open '%s' for reading: %s\n"),
- GetIsoFile(), strerror(errno));
+ fname, strerror(errno));
return -1;
}
size_main = get_size(cdHandle);
snprintf(image_str, sizeof(image_str) - 6*4 - 1,
- "Loaded CD Image: %s", GetIsoFile());
+ "Loaded CD Image: %s", fname);
cddaBigEndian = FALSE;
subChanMixed = FALSE;
cdrIsoMultidiskCount = 1;
multifile = 0;
- CDR_getBuffer = ISOgetBuffer;
+ ISOgetBuffer = ISOgetBuffer_normal;
cdimg_read_func = cdread_normal;
cdimg_read_sub_func = NULL;
- if (parsetoc(GetIsoFile()) == 0) {
+ if (parsetoc(fname) == 0) {
strcat(image_str, "[+toc]");
}
- else if (parseccd(GetIsoFile()) == 0) {
+ else if (parseccd(fname) == 0) {
strcat(image_str, "[+ccd]");
}
- else if (parsemds(GetIsoFile()) == 0) {
+ else if (parsemds(fname) == 0) {
strcat(image_str, "[+mds]");
}
- else if (parsecue(GetIsoFile()) == 0) {
+ else if (parsecue(fname) == 0) {
strcat(image_str, "[+cue]");
}
- if (handlepbp(GetIsoFile()) == 0) {
+ if (handlepbp(fname) == 0) {
strcat(image_str, "[+pbp]");
- CDR_getBuffer = ISOgetBuffer_compr;
+ ISOgetBuffer = ISOgetBuffer_compr;
cdimg_read_func = cdread_compressed;
}
- else if (handlecbin(GetIsoFile()) == 0) {
+ else if (handlecbin(fname) == 0) {
strcat(image_str, "[+cbin]");
- CDR_getBuffer = ISOgetBuffer_compr;
+ ISOgetBuffer = ISOgetBuffer_compr;
cdimg_read_func = cdread_compressed;
}
#ifdef HAVE_CHD
- else if (handlechd(GetIsoFile()) == 0) {
+ else if (handlechd(fname) == 0) {
strcat(image_str, "[+chd]");
- CDR_getBuffer = ISOgetBuffer_chd;
+ ISOgetBuffer = ISOgetBuffer_chd;
cdimg_read_func = cdread_chd;
cdimg_read_sub_func = cdread_sub_chd;
fclose(cdHandle);
}
#endif
- if (!subChanMixed && opensubfile(GetIsoFile()) == 0) {
+ if (!subChanMixed && opensubfile(fname) == 0) {
strcat(image_str, "[+sub]");
}
- if (opensbifile(GetIsoFile()) == 0) {
+ if (opensbifile(fname) == 0) {
strcat(image_str, "[+sbi]");
}
// maybe user selected metadata file instead of main .bin ..
- bin_filename = GetIsoFile();
+ bin_filename = fname;
if (cdHandle && size_main < 2352 * 0x10) {
static const char *exts[] = { ".bin", ".BIN", ".img", ".IMG" };
FILE *tmpf = NULL;
cdimg_read_sub_func = NULL;
}
- if (Config.AsyncCD) {
- readThreadStart();
- }
return 0;
}
-static long CALLBACK ISOclose(void) {
+int ISOclose(void)
+{
int i;
if (cdHandle != NULL) {
UnloadSBI();
memset(cdbuffer, 0, sizeof(cdbuffer));
- CDR_getBuffer = ISOgetBuffer;
-
- if (Config.AsyncCD) {
- readThreadStop();
- }
+ ISOgetBuffer = ISOgetBuffer_normal;
return 0;
}
-static long CALLBACK ISOinit(void) {
+int ISOinit(void)
+{
assert(cdHandle == NULL);
assert(subHandle == NULL);
+ numtracks = 0;
return 0; // do nothing
}
-static long CALLBACK ISOshutdown(void) {
- ISOclose();
- return 0;
+int ISOshutdown(void)
+{
+ return ISOclose();
}
// return Starting and Ending Track
// buffer:
// byte 0 - start track
// byte 1 - end track
-static long CALLBACK ISOgetTN(unsigned char *buffer) {
+int ISOgetTN(unsigned char *buffer)
+{
buffer[0] = 1;
if (numtracks > 0) {
// return Track Time
// buffer:
-// byte 0 - frame
+// byte 0 - minute
// byte 1 - second
-// byte 2 - minute
-static long CALLBACK ISOgetTD(unsigned char track, unsigned char *buffer) {
+// byte 2 - frame
+int ISOgetTD(int track, unsigned char *buffer)
+{
if (track == 0) {
unsigned int sect;
- unsigned char time[3];
sect = msf2sec(ti[numtracks].start) + msf2sec(ti[numtracks].length);
- sec2msf(sect, (char *)time);
- buffer[2] = time[0];
- buffer[1] = time[1];
- buffer[0] = time[2];
+ sec2msf(sect, buffer);
}
else if (numtracks > 0 && track <= numtracks) {
- buffer[2] = ti[track].start[0];
- buffer[1] = ti[track].start[1];
- buffer[0] = ti[track].start[2];
+ memcpy(buffer, ti[track].start, 3);
}
else {
buffer[2] = 0;
}
// decode 'raw' subchannel data ripped by cdrdao
-static void DecodeRawSubData(void) {
+static void DecodeRawSubData(unsigned char *subbuffer) {
unsigned char subQData[12];
int i;
}
// read track
-// time: byte 0 - minute; byte 1 - second; byte 2 - frame
-// uses bcd format
-static boolean CALLBACK ISOreadTrack(unsigned char *time) {
- int sector = MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2]));
+// time: byte 0 - minute; byte 1 - second; byte 2 - frame (non-bcd)
+// buf: if NULL, data is kept in internal buffer accessible by ISOgetBuffer()
+int ISOreadTrack(const unsigned char *time, void *buf)
+{
+ int sector = msf2sec(time);
long ret;
if (!cdHandle && !chd_img)
- return 0;
+ return -1;
+ if (numtracks > 1 && sector >= msf2sec(ti[2].start))
+ return ISOreadCDDA(time, buf);
+
+ sector -= 2 * 75;
if (pregapOffset && sector >= pregapOffset)
sector -= 2 * 75;
- ret = cdimg_read_func(cdHandle, 0, cdbuffer, sector);
- if (ret < 12*2 + 2048)
- return 0;
-
- return 1;
-}
+ ret = cdimg_read_func(cdHandle, 0, buf, sector);
+ if (ret < 12*2 + 2048) {
+ if (multifile && sector >= msf2sec(ti[1].length)) {
+ // assume a gap not backed by a file
+ memset(buf, 0, CD_FRAMESIZE_RAW);
+ return 0;
+ }
+ return -1;
+ }
-// plays cdda audio
-// sector: byte 0 - minute; byte 1 - second; byte 2 - frame
-// does NOT uses bcd format
-static long CALLBACK ISOplay(unsigned char *time) {
return 0;
}
-// stops cdda audio
-static long CALLBACK ISOstop(void) {
- return 0;
-}
+// read subchannel data
+int ISOreadSub(const unsigned char *time, void *buffer)
+{
+ int ret, sector = MSF2SECT(time[0], time[1], time[2]);
-// gets subchannel data
-static unsigned char* CALLBACK ISOgetBufferSub(int sector) {
if (pregapOffset && sector >= pregapOffset) {
sector -= 2 * 75;
if (sector < pregapOffset) // ?
- return NULL;
+ return -1;
}
if (cdimg_read_sub_func != NULL) {
- if (cdimg_read_sub_func(cdHandle, sector) != SUB_FRAMESIZE)
- return NULL;
+ if ((ret = cdimg_read_sub_func(cdHandle, sector, buffer)))
+ return ret;
}
else if (subHandle != NULL) {
if (fseeko(subHandle, sector * SUB_FRAMESIZE, SEEK_SET))
- return NULL;
- if (fread(subbuffer, 1, SUB_FRAMESIZE, subHandle) != SUB_FRAMESIZE)
- return NULL;
+ return -1;
+ if (fread(buffer, 1, SUB_FRAMESIZE, subHandle) != SUB_FRAMESIZE)
+ return -1;
}
else {
- return NULL;
+ return -1;
}
- if (subChanRaw) DecodeRawSubData();
- return subbuffer;
+ if (subChanRaw)
+ DecodeRawSubData(buffer);
+ return 0;
}
-static long CALLBACK ISOgetStatus(struct CdrStat *stat) {
+int ISOgetStatus(struct CdrStat *stat)
+{
CDR__getStatus(stat);
// BIOS - boot ID (CD type)
}
// read CDDA sector into buffer
-long CALLBACK ISOreadCDDA(unsigned char m, unsigned char s, unsigned char f, unsigned char *buffer) {
- unsigned char msf[3] = {m, s, f};
+int ISOreadCDDA(const unsigned char *time, void *buffer)
+{
unsigned int track, track_start = 0;
FILE *handle = cdHandle;
unsigned int cddaCurPos;
- int ret;
+ int ret, ret_clear = -1;
- cddaCurPos = msf2sec((char *)msf);
+ cddaCurPos = msf2sec(time);
// find current track index
for (track = numtracks; ; track--) {
// data tracks play silent
if (ti[track].type != CDDA) {
- memset(buffer, 0, CD_FRAMESIZE_RAW);
- return 0;
+ ret_clear = 0;
+ goto clear_return;
}
if (multifile) {
}
}
}
- if (!handle && !chd_img) {
- memset(buffer, 0, CD_FRAMESIZE_RAW);
- return -1;
- }
+ if (!handle && !chd_img)
+ goto clear_return;
ret = cdimg_read_func(handle, ti[track].start_offset,
buffer, cddaCurPos - track_start);
if (ret != CD_FRAMESIZE_RAW) {
- memset(buffer, 0, CD_FRAMESIZE_RAW);
- return -1;
+ if (multifile && cddaCurPos - track_start >= msf2sec(ti[track].length))
+ ret_clear = 0; // gap
+ goto clear_return;
}
- if (cddaBigEndian) {
+ if (cddaBigEndian && buffer) {
+ unsigned char tmp, *buf = buffer;
int i;
- unsigned char tmp;
for (i = 0; i < CD_FRAMESIZE_RAW / 2; i++) {
- tmp = buffer[i * 2];
- buffer[i * 2] = buffer[i * 2 + 1];
- buffer[i * 2 + 1] = tmp;
+ tmp = buf[i * 2];
+ buf[i * 2] = buf[i * 2 + 1];
+ buf[i * 2 + 1] = tmp;
}
}
return 0;
-}
-
-void cdrIsoInit(void) {
- CDR_init = ISOinit;
- CDR_shutdown = ISOshutdown;
- CDR_open = ISOopen;
- CDR_close = ISOclose;
- CDR_getTN = ISOgetTN;
- CDR_getTD = ISOgetTD;
- CDR_readTrack = ISOreadTrack;
- CDR_getBuffer = ISOgetBuffer;
- CDR_play = ISOplay;
- CDR_stop = ISOstop;
- CDR_getBufferSub = ISOgetBufferSub;
- CDR_getStatus = ISOgetStatus;
- CDR_readCDDA = ISOreadCDDA;
-
- CDR_getDriveLetter = CDR__getDriveLetter;
- CDR_configure = CDR__configure;
- CDR_test = CDR__test;
- CDR_about = CDR__about;
- CDR_setfilename = CDR__setfilename;
- CDR_prefetch = CDR__prefetch;
- numtracks = 0;
-}
-
-int cdrIsoActive(void) {
- return (cdHandle || chd_img);
+clear_return:
+ if (buffer)
+ memset(buffer, 0, CD_FRAMESIZE_RAW);
+ return ret_clear;
}
extern "C" {
#endif
-void cdrIsoInit(void);
-int cdrIsoActive(void);
-unsigned char * CALLBACK ISOgetBuffer(void);
+struct CdrStat;
+
+int ISOinit(void);
+int ISOshutdown(void);
+int ISOopen(const char *fname);
+int ISOclose(void);
+int ISOgetTN(unsigned char *buffer);
+int ISOgetTD(int track, unsigned char *buffer);
+int ISOreadTrack(const unsigned char *time, void *buf);
+int ISOreadCDDA(const unsigned char *time, void *buffer);
+int ISOreadSub(const unsigned char *time, void *buffer);
+int ISOgetStatus(struct CdrStat *stat);
+
+extern void * (*ISOgetBuffer)(void);
extern unsigned int cdrIsoMultidiskCount;
extern unsigned int cdrIsoMultidiskSelect;
--- /dev/null
+/***************************************************************************
+ * This program 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 Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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. *
+ ***************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include "system.h"
+#include "plugins.h"
+#include "cdriso.h"
+#include "cdrom.h"
+#include "cdrom-async.h"
+
+#if 0
+#define acdrom_dbg printf
+#else
+#define acdrom_dbg(...)
+#endif
+
+#ifdef HAVE_CDROM
+
+#include "vfs/vfs_implementation.h"
+#include "vfs/vfs_implementation_cdrom.h"
+#include "../frontend/libretro-cdrom.h"
+
+static libretro_vfs_implementation_file *g_cd_handle;
+
+static int rcdrom_open(const char *name, u32 *total_lba)
+{
+ g_cd_handle = retro_vfs_file_open_impl(name, RETRO_VFS_FILE_ACCESS_READ,
+ RETRO_VFS_FILE_ACCESS_HINT_NONE);
+ if (!g_cd_handle) {
+ SysPrintf("retro_vfs_file_open failed for '%s'\n", name);
+ return -1;
+ }
+ else {
+ int ret = cdrom_set_read_speed_x(g_cd_handle, 4);
+ if (ret) SysPrintf("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 = MSF2SECT(last->min, last->sec, last->frame);
+ *total_lba = lba + last->track_size;
+ //cdrom_get_current_config_random_readable(acdrom.h);
+ //cdrom_get_current_config_multiread(acdrom.h);
+ //cdrom_get_current_config_cdread(acdrom.h);
+ //cdrom_get_current_config_profiles(acdrom.h);
+ return 0;
+ }
+}
+
+static void rcdrom_close(void)
+{
+ if (g_cd_handle) {
+ retro_vfs_file_close_impl(g_cd_handle);
+ g_cd_handle = NULL;
+ }
+}
+
+static int rcdrom_getTN(u8 *tn)
+{
+ const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc();
+ if (toc) {
+ tn[0] = 1;
+ tn[1] = toc->num_tracks;
+ return 0;
+ }
+ return -1;
+}
+
+static int rcdrom_getTD(u32 total_lba, u8 track, u8 *rt)
+{
+ const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc();
+ rt[0] = 0, rt[1] = 2, rt[2] = 0;
+ if (track == 0) {
+ lba2msf(total_lba + 150, &rt[0], &rt[1], &rt[2]);
+ }
+ else if (track <= toc->num_tracks) {
+ int i = track - 1;
+ rt[0] = toc->track[i].min;
+ rt[1] = toc->track[i].sec;
+ rt[2] = toc->track[i].frame;
+ }
+ return 0;
+}
+
+static int rcdrom_getStatus(struct CdrStat *stat)
+{
+ const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc();
+ stat->Type = toc->track[0].audio ? 2 : 1;
+ return 0;
+}
+
+#elif defined(USE_ASYNC_CDROM)
+
+#define g_cd_handle 0
+
+static int rcdrom_open(const char *name, u32 *total_lba) { return -1; }
+static void rcdrom_close(void) {}
+static int rcdrom_getTN(u8 *tn) { return -1; }
+static int rcdrom_getTD(u32 total_lba, u8 track, u8 *rt) { return -1; }
+static int rcdrom_getStatus(struct CdrStat *stat) { return -1; }
+
+static int cdrom_read_sector(void *stream, unsigned int lba, void *b) { return -1; }
+static int cdrom_is_media_inserted(void *stream) { return 0; }
+
+#endif
+
+#ifdef USE_ASYNC_CDROM
+
+#include "rthreads/rthreads.h"
+#include "retro_timers.h"
+
+struct cached_buf {
+ u32 lba;
+ u8 buf[CD_FRAMESIZE_RAW];
+ u8 buf_sub[SUB_FRAMESIZE];
+};
+static struct {
+ sthread_t *thread;
+ slock_t *read_lock;
+ slock_t *buf_lock;
+ scond_t *cond;
+ struct cached_buf *buf_cache;
+ u32 buf_cnt, thread_exit, do_prefetch, prefetch_failed, have_subchannel;
+ u32 total_lba, prefetch_lba;
+ int check_eject_delay;
+ u8 buf_local[CD_FRAMESIZE_RAW]; // single sector cache, not touched by the thread
+} acdrom;
+
+static void lbacache_do(u32 lba)
+{
+ unsigned char msf[3], buf[CD_FRAMESIZE_RAW], buf_sub[SUB_FRAMESIZE];
+ u32 i = lba % acdrom.buf_cnt;
+ int ret;
+
+ lba2msf(lba + 150, &msf[0], &msf[1], &msf[2]);
+ slock_lock(acdrom.read_lock);
+ if (g_cd_handle)
+ ret = cdrom_read_sector(g_cd_handle, lba, buf);
+ else
+ ret = ISOreadTrack(msf, buf);
+ if (acdrom.have_subchannel)
+ ret |= ISOreadSub(msf, buf_sub);
+
+ slock_lock(acdrom.buf_lock);
+ slock_unlock(acdrom.read_lock);
+ acdrom_dbg("c %d:%02d:%02d %2d m%d f%d\n", msf[0], msf[1], msf[2], ret,
+ buf[12+3], ((buf[12+4+2] >> 5) & 1) + 1);
+ if (ret) {
+ acdrom.do_prefetch = 0;
+ acdrom.prefetch_failed = 1;
+ slock_unlock(acdrom.buf_lock);
+ SysPrintf("prefetch: read failed for lba %d: %d\n", lba, ret);
+ return;
+ }
+ acdrom.prefetch_failed = 0;
+ acdrom.check_eject_delay = 100;
+
+ if (lba != acdrom.buf_cache[i].lba) {
+ acdrom.buf_cache[i].lba = lba;
+ memcpy(acdrom.buf_cache[i].buf, buf, sizeof(acdrom.buf_cache[i].buf));
+ if (acdrom.have_subchannel)
+ memcpy(acdrom.buf_cache[i].buf_sub, buf_sub, sizeof(buf_sub));
+ }
+ slock_unlock(acdrom.buf_lock);
+ if (g_cd_handle)
+ retro_sleep(0); // why does the main thread stall without this?
+}
+
+static int lbacache_get(unsigned int lba, void *buf, void *sub_buf)
+{
+ unsigned int i;
+ int ret = 0;
+
+ i = lba % acdrom.buf_cnt;
+ slock_lock(acdrom.buf_lock);
+ if (lba == acdrom.buf_cache[i].lba) {
+ if (!buf)
+ buf = acdrom.buf_local;
+ memcpy(buf, acdrom.buf_cache[i].buf, CD_FRAMESIZE_RAW);
+ if (sub_buf)
+ memcpy(sub_buf, acdrom.buf_cache[i].buf_sub, SUB_FRAMESIZE);
+ ret = 1;
+ }
+ slock_unlock(acdrom.buf_lock);
+ return ret;
+}
+
+// note: This has races on some vars but that's ok, main thread can deal
+// with it. Only unsafe buffer accesses and simultaneous reads are prevented.
+static void cdra_prefetch_thread(void *unused)
+{
+ u32 buf_cnt, lba, lba_to;
+
+ slock_lock(acdrom.buf_lock);
+ while (!acdrom.thread_exit)
+ {
+#ifdef __GNUC__
+ __asm__ __volatile__("":::"memory"); // barrier
+#endif
+ if (!acdrom.do_prefetch)
+ scond_wait(acdrom.cond, acdrom.buf_lock);
+ if (!acdrom.do_prefetch || acdrom.thread_exit)
+ continue;
+
+ buf_cnt = acdrom.buf_cnt;
+ lba = acdrom.prefetch_lba;
+ lba_to = lba + buf_cnt;
+ if (lba_to > acdrom.total_lba)
+ lba_to = acdrom.total_lba;
+ for (; lba < lba_to; lba++) {
+ if (lba != acdrom.buf_cache[lba % buf_cnt].lba)
+ break;
+ }
+ if (lba == lba_to || lba >= acdrom.total_lba) {
+ // caching complete
+ acdrom.do_prefetch = 0;
+ continue;
+ }
+
+ slock_unlock(acdrom.buf_lock);
+ lbacache_do(lba);
+ slock_lock(acdrom.buf_lock);
+ }
+ slock_unlock(acdrom.buf_lock);
+}
+
+void cdra_stop_thread(void)
+{
+ acdrom.thread_exit = 1;
+ if (acdrom.buf_lock) {
+ slock_lock(acdrom.buf_lock);
+ acdrom.do_prefetch = 0;
+ if (acdrom.cond)
+ scond_signal(acdrom.cond);
+ slock_unlock(acdrom.buf_lock);
+ }
+ if (acdrom.thread) {
+ sthread_join(acdrom.thread);
+ acdrom.thread = NULL;
+ }
+ if (acdrom.cond) { scond_free(acdrom.cond); acdrom.cond = NULL; }
+ if (acdrom.buf_lock) { slock_free(acdrom.buf_lock); acdrom.buf_lock = NULL; }
+ if (acdrom.read_lock) { slock_free(acdrom.read_lock); acdrom.read_lock = NULL; }
+ free(acdrom.buf_cache);
+ acdrom.buf_cache = NULL;
+}
+
+// the thread is optional, if anything fails we can do direct reads
+static void cdra_start_thread(void)
+{
+ cdra_stop_thread();
+ acdrom.thread_exit = acdrom.prefetch_lba = acdrom.do_prefetch = 0;
+ acdrom.prefetch_failed = 0;
+ if (acdrom.buf_cnt == 0)
+ return;
+ acdrom.buf_cache = calloc(acdrom.buf_cnt, sizeof(acdrom.buf_cache[0]));
+ acdrom.buf_lock = slock_new();
+ acdrom.read_lock = slock_new();
+ acdrom.cond = scond_new();
+ if (acdrom.buf_cache && acdrom.buf_lock && acdrom.read_lock && acdrom.cond)
+ {
+ int i;
+ acdrom.thread = sthread_create(cdra_prefetch_thread, NULL);
+ for (i = 0; i < acdrom.buf_cnt; i++)
+ acdrom.buf_cache[i].lba = ~0;
+ }
+ if (acdrom.thread) {
+ SysPrintf("cdrom precache: %d buffers%s\n",
+ acdrom.buf_cnt, acdrom.have_subchannel ? " +sub" : "");
+ }
+ else {
+ SysPrintf("cdrom precache thread init failed.\n");
+ cdra_stop_thread();
+ }
+}
+
+int cdra_init(void)
+{
+ return ISOinit();
+}
+
+void cdra_shutdown(void)
+{
+ cdra_close();
+}
+
+int cdra_open(void)
+{
+ const char *name = GetIsoFile();
+ u8 buf_sub[SUB_FRAMESIZE];
+ int ret = -1, ret2;
+
+ acdrom_dbg("%s %s\n", __func__, name);
+ acdrom.have_subchannel = 0;
+ if (!strncmp(name, "cdrom:", 6))
+ ret = rcdrom_open(name, &acdrom.total_lba);
+
+ // try ISO even if it's cdrom:// as it might work through libretro vfs
+ if (ret < 0) {
+ ret = ISOopen(name);
+ if (ret == 0) {
+ u8 msf[3];
+ ISOgetTD(0, msf);
+ acdrom.total_lba = MSF2SECT(msf[0], msf[1], msf[2]);
+ msf[0] = 0; msf[1] = 2; msf[2] = 16;
+ ret2 = ISOreadSub(msf, buf_sub);
+ acdrom.have_subchannel = (ret2 == 0);
+ }
+ }
+ if (ret == 0)
+ cdra_start_thread();
+ return ret;
+}
+
+void cdra_close(void)
+{
+ acdrom_dbg("%s\n", __func__);
+ cdra_stop_thread();
+ if (g_cd_handle)
+ rcdrom_close();
+ else
+ ISOclose();
+}
+
+int cdra_getTN(unsigned char *tn)
+{
+ int ret;
+ if (g_cd_handle)
+ ret = rcdrom_getTN(tn);
+ else
+ ret = ISOgetTN(tn);
+ acdrom_dbg("%s -> %d %d\n", __func__, tn[0], tn[1]);
+ return ret;
+}
+
+int cdra_getTD(int track, unsigned char *rt)
+{
+ int ret;
+ if (g_cd_handle)
+ ret = rcdrom_getTD(acdrom.total_lba, track, rt);
+ else
+ ret = ISOgetTD(track, rt);
+ //acdrom_dbg("%s %d -> %d:%02d:%02d\n", __func__, track, rt[2], rt[1], rt[0]);
+ return ret;
+}
+
+int cdra_prefetch(unsigned char m, unsigned char s, unsigned char f)
+{
+ u32 lba = MSF2SECT(m, s, f);
+ int ret = 1;
+ if (acdrom.cond) {
+ acdrom.prefetch_lba = lba;
+ acdrom.do_prefetch = 1;
+ scond_signal(acdrom.cond);
+ }
+ if (acdrom.buf_cache && !acdrom.prefetch_failed) {
+ u32 c = acdrom.buf_cnt;
+ if (c)
+ ret = acdrom.buf_cache[lba % c].lba == lba;
+ acdrom_dbg("p %d:%02d:%02d %d\n", m, s, f, ret);
+ }
+ return ret;
+}
+
+static int cdra_do_read(const unsigned char *time, int cdda,
+ void *buf, void *buf_sub)
+{
+ u32 lba = MSF2SECT(time[0], time[1], time[2]);
+ int hit = 0, ret = -1, read_locked = 0;
+ do
+ {
+ if (acdrom.buf_lock) {
+ hit = lbacache_get(lba, buf, buf_sub);
+ if (hit)
+ break;
+ }
+ if (acdrom.read_lock) {
+ // maybe still prefetching
+ slock_lock(acdrom.read_lock);
+ read_locked = 1;
+ hit = lbacache_get(lba, buf, buf_sub);
+ if (hit) {
+ hit = 2;
+ break;
+ }
+ }
+ acdrom.do_prefetch = 0;
+ if (!buf)
+ buf = acdrom.buf_local;
+ if (g_cd_handle)
+ ret = cdrom_read_sector(g_cd_handle, lba, buf);
+ else if (buf_sub)
+ ret = ISOreadSub(time, buf_sub);
+ else if (cdda)
+ ret = ISOreadCDDA(time, buf);
+ else
+ ret = ISOreadTrack(time, buf);
+ if (ret)
+ SysPrintf("cdrom read failed for lba %d: %d\n", lba, ret);
+ }
+ while (0);
+ if (read_locked)
+ slock_unlock(acdrom.read_lock);
+ if (hit)
+ ret = 0;
+ acdrom.check_eject_delay = ret ? 0 : 100;
+ acdrom_dbg("f%c %d:%02d:%02d %d%s\n",
+ buf_sub ? 's' : (cdda ? 'c' : 'd'),
+ time[0], time[1], time[2], hit, ret ? " ERR" : "");
+ return ret;
+}
+
+// time: msf in non-bcd format
+int cdra_readTrack(const unsigned char *time)
+{
+ if (!acdrom.thread && !g_cd_handle) {
+ // just forward to ISOreadTrack to avoid extra copying
+ return ISOreadTrack(time, NULL);
+ }
+ return cdra_do_read(time, 0, NULL, NULL);
+}
+
+int cdra_readCDDA(const unsigned char *time, void *buffer)
+{
+ return cdra_do_read(time, 1, buffer, NULL);
+}
+
+int cdra_readSub(const unsigned char *time, void *buffer)
+{
+ if (!acdrom.thread && !g_cd_handle)
+ return ISOreadSub(time, buffer);
+ if (!acdrom.have_subchannel)
+ return -1;
+ acdrom_dbg("s %d:%02d:%02d\n", time[0], time[1], time[2]);
+ return cdra_do_read(time, 0, NULL, buffer);
+}
+
+// pointer to cached buffer from last cdra_readTrack() call
+void *cdra_getBuffer(void)
+{
+ //acdrom_dbg("%s\n", __func__);
+ if (!acdrom.thread && !g_cd_handle)
+ return ISOgetBuffer();
+ return acdrom.buf_local + 12;
+}
+
+int cdra_getStatus(struct CdrStat *stat)
+{
+ int ret;
+ CDR__getStatus(stat);
+ if (g_cd_handle)
+ ret = rcdrom_getStatus(stat);
+ else
+ ret = ISOgetStatus(stat);
+ return ret;
+}
+
+int cdra_is_physical(void)
+{
+ return !!g_cd_handle;
+}
+
+int cdra_check_eject(int *inserted)
+{
+ if (!g_cd_handle || acdrom.do_prefetch || acdrom.check_eject_delay-- > 0)
+ return 0;
+ acdrom.check_eject_delay = 100;
+ *inserted = cdrom_is_media_inserted(g_cd_handle); // 1-2ms
+ return 1;
+}
+
+void cdra_set_buf_count(int newcount)
+{
+ if (acdrom.buf_cnt == newcount)
+ return;
+ cdra_stop_thread();
+ acdrom.buf_cnt = newcount;
+ cdra_start_thread();
+}
+
+#else
+
+// phys. CD-ROM without a cache is unusable so not implemented
+#ifdef HAVE_CDROM
+#error "HAVE_CDROM requires USE_ASYNC_CDROM"
+#endif
+
+// just forward to cdriso
+int cdra_init(void)
+{
+ return ISOinit();
+}
+
+void cdra_shutdown(void)
+{
+ ISOshutdown();
+}
+
+int cdra_open(void)
+{
+ return ISOopen(GetIsoFile());
+}
+
+void cdra_close(void)
+{
+ ISOclose();
+}
+
+int cdra_getTN(unsigned char *tn)
+{
+ return ISOgetTN(tn);
+}
+
+int cdra_getTD(int track, unsigned char *rt)
+{
+ return ISOgetTD(track, rt);
+}
+
+int cdra_prefetch(unsigned char m, unsigned char s, unsigned char f)
+{
+ return 1; // always hit
+}
+
+// time: msf in non-bcd format
+int cdra_readTrack(const unsigned char *time)
+{
+ return ISOreadTrack(time, NULL);
+}
+
+int cdra_readCDDA(const unsigned char *time, void *buffer)
+{
+ return ISOreadCDDA(time, buffer);
+}
+
+int cdra_readSub(const unsigned char *time, void *buffer)
+{
+ return ISOreadSub(time, buffer);
+}
+
+// pointer to cached buffer from last cdra_readTrack() call
+void *cdra_getBuffer(void)
+{
+ return ISOgetBuffer();
+}
+
+int cdra_getStatus(struct CdrStat *stat)
+{
+ return ISOgetStatus(stat);
+}
+
+int cdra_is_physical(void) { return 0; }
+int cdra_check_eject(int *inserted) { return 0; }
+void cdra_stop_thread(void) {}
+void cdra_set_buf_count(int newcount) {}
+
+#endif
+
+// vim:sw=3:ts=3:expandtab
--- /dev/null
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct CdrStat;
+
+int cdra_init(void);
+void cdra_shutdown(void);
+int cdra_open(void);
+void cdra_close(void);
+int cdra_getTN(unsigned char *tn);
+int cdra_getTD(int track, unsigned char *rt);
+int cdra_getStatus(struct CdrStat *stat);
+int cdra_readTrack(const unsigned char *time);
+int cdra_readCDDA(const unsigned char *time, void *buffer);
+int cdra_readSub(const unsigned char *time, void *buffer);
+int cdra_prefetch(unsigned char m, unsigned char s, unsigned char f);
+
+int cdra_is_physical(void);
+int cdra_check_eject(int *inserted);
+void cdra_stop_thread(void);
+void cdra_set_buf_count(int count);
+
+void *cdra_getBuffer(void);
+
+#ifdef __cplusplus
+}
+#endif
#include <assert.h>
#include "cdrom.h"
+#include "cdrom-async.h"
#include "misc.h"
#include "ppf.h"
#include "psxdma.h"
} cdr;
static s16 read_buf[CD_FRAMESIZE_RAW/2];
+struct SubQ {
+ char res0[12];
+ unsigned char ControlAndADR;
+ unsigned char TrackNumber;
+ unsigned char IndexNumber;
+ unsigned char TrackRelativeAddress[3];
+ unsigned char Filler;
+ unsigned char AbsoluteAddress[3];
+ unsigned char CRC[2];
+ char res1[72];
+};
+
/* CD-ROM magic numbers */
#define CdlSync 0 /* nocash documentation : "Uh, actually, returns error code 40h = Invalid Command...?" */
#define CdlNop 1
return ((msf[0] * 60 + msf[1]) * 75) + msf[2];
}
-// for that weird psemu API..
-static unsigned int fsm2sec(const u8 *msf) {
- return ((msf[2] * 60 + msf[1]) * 75) + msf[0];
-}
-
-static void sec2msf(unsigned int s, u8 *msf) {
- msf[0] = s / 75 / 60;
- s = s - msf[0] * 75 * 60;
- msf[1] = s / 75;
- s = s - msf[1] * 75;
- msf[2] = s;
-}
-
// cdrPlayReadInterrupt
#define CDRPLAYREAD_INT(eCycle, isFirst) { \
u32 e_ = eCycle; \
}
#define StopCdda() { \
- if (cdr.Play && !Config.Cdda) CDR_stop(); \
cdr.Play = FALSE; \
cdr.FastForward = 0; \
cdr.FastBackward = 0; \
//StopReading();
SetPlaySeekRead(cdr.StatP, 0);
- if (CDR_getStatus(&cdr_stat) == -1)
+ if (cdra_getStatus(&cdr_stat) == -1)
return;
if (cdr_stat.Status & STATUS_SHELLOPEN)
break;
case DRIVESTATE_LID_OPEN:
- if (CDR_getStatus(&cdr_stat) == -1)
+ if (cdra_getStatus(&cdr_stat) != 0)
cdr_stat.Status &= ~STATUS_SHELLOPEN;
// 02, 12, 10
current = msf2sec(time);
for (cdr.CurTrack = 1; cdr.CurTrack < cdr.ResultTN[1]; cdr.CurTrack++) {
- CDR_getTD(cdr.CurTrack + 1, cdr.ResultTD);
- sect = fsm2sec(cdr.ResultTD);
+ cdra_getTD(cdr.CurTrack + 1, cdr.ResultTD);
+ sect = msf2sec(cdr.ResultTD);
if (sect - current >= 150)
break;
}
unsigned int this_s, start_s, next_s, pregap;
int relative_s;
- CDR_getTD(cdr.CurTrack, start);
+ cdra_getTD(cdr.CurTrack, start);
if (cdr.CurTrack + 1 <= cdr.ResultTN[1]) {
pregap = 150;
- CDR_getTD(cdr.CurTrack + 1, next);
+ cdra_getTD(cdr.CurTrack + 1, next);
}
else {
// last track - cd size
pregap = 0;
- next[0] = cdr.SetSectorEnd[2];
- next[1] = cdr.SetSectorEnd[1];
- next[2] = cdr.SetSectorEnd[0];
+ memcpy(next, cdr.SetSectorEnd, 3);
}
this_s = msf2sec(time);
- start_s = fsm2sec(start);
- next_s = fsm2sec(next);
+ start_s = msf2sec(start);
+ next_s = msf2sec(next);
cdr.TrackChanged = FALSE;
cdr.subq.Index = 0;
relative_s = -relative_s;
}
- sec2msf(relative_s, cdr.subq.Relative);
+ lba2msf(relative_s, &cdr.subq.Relative[0],
+ &cdr.subq.Relative[1], &cdr.subq.Relative[2]);
cdr.subq.Track = itob(cdr.CurTrack);
cdr.subq.Relative[0] = itob(cdr.subq.Relative[0]);
static int ReadTrack(const u8 *time)
{
- unsigned char tmp[3];
- int read_ok;
+ int ret;
- tmp[0] = itob(time[0]);
- tmp[1] = itob(time[1]);
- tmp[2] = itob(time[2]);
+ CDR_LOG("ReadTrack *** %02d:%02d:%02d\n", tmp[0], tmp[1], tmp[2]);
- CDR_LOG("ReadTrack *** %02x:%02x:%02x\n", tmp[0], tmp[1], tmp[2]);
-
- if (memcmp(cdr.Prev, tmp, 3) == 0)
+ if (memcmp(cdr.Prev, time, 3) == 0)
return 1;
- read_ok = CDR_readTrack(tmp);
- if (read_ok)
- memcpy(cdr.Prev, tmp, 3);
- return read_ok;
+ ret = cdra_readTrack(time);
+ if (ret != 0)
+ memcpy(cdr.Prev, time, 3);
+ return ret == 0;
}
static void UpdateSubq(const u8 *time)
{
- const struct SubQ *subq;
- int s = MSF2SECT(time[0], time[1], time[2]);
+ int ret = -1, s = MSF2SECT(time[0], time[1], time[2]);
+ struct SubQ subq;
u16 crc;
if (CheckSBI(s))
return;
- subq = (struct SubQ *)CDR_getBufferSub(s);
- if (subq != NULL && cdr.CurTrack == 1) {
- crc = calcCrc((u8 *)subq + 12, 10);
- if (crc == (((u16)subq->CRC[0] << 8) | subq->CRC[1])) {
- cdr.subq.Track = subq->TrackNumber;
- cdr.subq.Index = subq->IndexNumber;
- memcpy(cdr.subq.Relative, subq->TrackRelativeAddress, 3);
- memcpy(cdr.subq.Absolute, subq->AbsoluteAddress, 3);
+ if (cdr.CurTrack == 1)
+ ret = cdra_readSub(time, &subq);
+ if (ret == 0) {
+ crc = calcCrc((u8 *)&subq + 12, 10);
+ if (crc == (((u16)subq.CRC[0] << 8) | subq.CRC[1])) {
+ cdr.subq.Track = subq.TrackNumber;
+ cdr.subq.Index = subq.IndexNumber;
+ memcpy(cdr.subq.Relative, subq.TrackRelativeAddress, 3);
+ memcpy(cdr.subq.Absolute, subq.AbsoluteAddress, 3);
}
else {
CDR_LOG_I("subq bad crc @%02d:%02d:%02d\n",
void cdrPlayReadInterrupt(void)
{
- int hit = CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
+ int hit = cdra_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
if (!hit && cdr.PhysCdPropagations++ < 222) {
// this propagates real cdrom delays to the emulated game
CDRPLAYREAD_INT(cdReadTime / 2, 0);
cdr.DriveState = DRIVESTATE_PAUSED;
}
else {
- CDR_readCDDA(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], (u8 *)read_buf);
+ cdra_readCDDA(cdr.SetSectorPlay, read_buf);
}
if (!cdr.IrqStat && (cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT)))
}
msfiAdd(cdr.SetSectorPlay, 1);
- CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
+ cdra_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
// update for CdlGetlocP/autopause
generate_subq(cdr.SetSectorPlay);
static void softReset(void)
{
- CDR_getStatus(&cdr_stat);
+ cdra_getStatus(&cdr_stat);
if (cdr_stat.Status & STATUS_SHELLOPEN) {
cdr.DriveState = DRIVESTATE_LID_OPEN;
cdr.StatP = STATUS_SHELLOPEN;
u32 second_resp_time = 0;
const void *buf;
u8 ParamC;
- u8 set_loc[3];
int read_ok;
u16 not_ready = 0;
u8 IrqStat = Acknowledge;
}
if (cdr.Irq1Pending) {
// hand out the "newest" sector, according to nocash
- cdrUpdateTransferBuf(CDR_getBuffer());
+ cdrUpdateTransferBuf(cdra_getBuffer());
CDR_LOG_I("%x:%02x:%02x loaded on ack, cmd=%02x res=%02x\n",
cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2],
cdr.CmdInProgress, cdr.Irq1Pending);
}
else
{
+ u8 set_loc[3];
for (i = 0; i < 3; i++)
set_loc[i] = btoi(cdr.Param[i]);
if ((msfiEq(cdr.SetSector, set_loc)) //|| msfiEq(cdr.Param, cdr.Transfer))
CDR_LOG("PLAY track %d\n", cdr.CurTrack);
- if (CDR_getTD((u8)cdr.CurTrack, cdr.ResultTD) != -1) {
- for (i = 0; i < 3; i++)
- set_loc[i] = cdr.ResultTD[2 - i];
- seekTime = cdrSeekTime(set_loc);
- memcpy(cdr.SetSectorPlay, set_loc, 3);
+ if (cdra_getTD(cdr.CurTrack, cdr.ResultTD) != -1) {
+ seekTime = cdrSeekTime(cdr.ResultTD);
+ memcpy(cdr.SetSectorPlay, cdr.ResultTD, 3);
}
}
else if (cdr.SetlocPending) {
cdr.ReportDelay = 60;
cdr.sectorsRead = 0;
- if (!Config.Cdda)
- CDR_play(cdr.SetSectorPlay);
-
SetPlaySeekRead(cdr.StatP, STATUS_SEEK | STATUS_ROTATING);
// BIOS player - set flag again
case CdlStop:
if (cdr.Play) {
// grab time for current track
- CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD);
-
- cdr.SetSectorPlay[0] = cdr.ResultTD[2];
- cdr.SetSectorPlay[1] = cdr.ResultTD[1];
- cdr.SetSectorPlay[2] = cdr.ResultTD[0];
+ cdra_getTD(cdr.CurTrack, cdr.ResultTD);
+ memcpy(cdr.SetSectorPlay, cdr.ResultTD, 3);
}
StopCdda();
break;
case CdlGetTN:
- if (CDR_getTN(cdr.ResultTN) == -1) {
+ if (cdra_getTN(cdr.ResultTN) != 0) {
assert(0);
}
SetResultSize_(3);
case CdlGetTD:
cdr.Track = btoi(cdr.Param[0]);
- if (CDR_getTD(cdr.Track, cdr.ResultTD) == -1) {
+ if (cdra_getTD(cdr.Track, cdr.ResultTD) != 0) {
error = ERROR_BAD_ARGVAL;
goto set_error;
}
SetResultSize_(3);
- cdr.Result[1] = itob(cdr.ResultTD[2]);
+ cdr.Result[1] = itob(cdr.ResultTD[0]);
cdr.Result[2] = itob(cdr.ResultTD[1]);
// no sector number
- //cdr.Result[3] = itob(cdr.ResultTD[0]);
+ //cdr.Result[3] = itob(cdr.ResultTD[2]);
break;
case CdlSeekL:
seekTime = cdrSeekTime(cdr.SetSector);
memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
cdr.DriveState = DRIVESTATE_SEEK;
- CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1],
+ cdra_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1],
cdr.SetSectorPlay[2]);
/*
Crusaders of Might and Magic = 0.5x-4x
Find_CurTrack(cdr.SetSectorPlay);
read_ok = ReadTrack(cdr.SetSectorPlay);
- if (read_ok && (buf = CDR_getBuffer()))
+ if (read_ok && (buf = cdra_getBuffer()))
memcpy(cdr.LocL, buf, 8);
UpdateSubq(cdr.SetSectorPlay);
cdr.DriveState = DRIVESTATE_STANDBY;
cdr.Result[3] = 0;
// 0x10 - audio | 0x40 - disk missing | 0x80 - unlicensed
- if (CDR_getStatus(&cdr_stat) == -1 || cdr_stat.Type == 0 || cdr_stat.Type == 0xff) {
+ if (cdra_getStatus(&cdr_stat) != 0 || cdr_stat.Type == 0 || cdr_stat.Type == 0xff) {
cdr.Result[1] = 0xc0;
}
else {
cdr.SubqForwardSectors = 1;
cdr.sectorsRead = 0;
cdr.DriveState = DRIVESTATE_SEEK;
- CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1],
+ cdra_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1],
cdr.SetSectorPlay[2]);
cycles = (cdr.Mode & MODE_SPEED) ? cdReadTime : cdReadTime * 2;
read_ok = ReadTrack(cdr.SetSectorPlay);
if (read_ok)
- buf = CDR_getBuffer();
+ buf = cdra_getBuffer();
if (buf == NULL)
read_ok = 0;
cdrReadInterruptSetResult(cdr.StatP);
msfiAdd(cdr.SetSectorPlay, 1);
- CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
+ cdra_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
CDRPLAYREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime, 0);
}
static void getCdInfo(void)
{
- u8 tmp;
-
- CDR_getTN(cdr.ResultTN);
- CDR_getTD(0, cdr.SetSectorEnd);
- tmp = cdr.SetSectorEnd[0];
- cdr.SetSectorEnd[0] = cdr.SetSectorEnd[2];
- cdr.SetSectorEnd[2] = tmp;
+ cdra_getTN(cdr.ResultTN);
+ cdra_getTD(0, cdr.SetSectorEnd);
}
void cdrReset() {
u32 tmp;
u8 tmpp[3];
- if (Mode == 0 && !Config.Cdda)
- CDR_stop();
-
- cdr.freeze_ver = 0x63647202;
+ cdr.freeze_ver = 0x63647203;
gzfreeze(&cdr, sizeof(cdr));
if (Mode == 1) {
cdr.SubqForwardSectors = SUBQ_FORWARD_SECTORS;
// read right sub data
- tmpp[0] = btoi(cdr.Prev[0]);
- tmpp[1] = btoi(cdr.Prev[1]);
- tmpp[2] = btoi(cdr.Prev[2]);
+ memcpy(tmpp, cdr.Prev, sizeof(tmpp));
+ if (cdr.freeze_ver < 0x63647203) {
+ tmpp[0] = btoi(tmpp[0]);
+ tmpp[1] = btoi(tmpp[1]);
+ tmpp[2] = btoi(tmpp[2]);
+ }
cdr.Prev[0]++;
ReadTrack(tmpp);
memcpy(cdr.SetSectorPlay, cdr.SetSector, 3);
Find_CurTrack(cdr.SetSectorPlay);
- if (!Config.Cdda)
- CDR_play(cdr.SetSectorPlay);
}
if (!cdr.Muted)
ll = cdr.AttenuatorLeftToLeft, lr = cdr.AttenuatorLeftToLeft,
#define MIN_VALUE(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
#define MAX_VALUE(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })
-#define MSF2SECT(m, s, f) (((m) * 60 + (s) - 2) * 75 + (f))
-
#define CD_FRAMESIZE_RAW 2352
#define DATA_SIZE (CD_FRAMESIZE_RAW - 12)
#define SUB_FRAMESIZE 96
+#define MSF2SECT(m, s, f) (((m) * 60 + (s) - 2) * 75 + (f))
+
+static inline void lba2msf(unsigned int lba, u8 *m, u8 *s, u8 *f) {
+ *m = lba / 75 / 60;
+ lba = lba - *m * 75 * 60;
+ *s = lba / 75;
+ lba = lba - *s * 75;
+ *f = lba;
+}
+
void cdrReset();
void cdrInterrupt(void);
#include "misc.h"
#include "sio.h"
#include "ppf.h"
+#include "cdrom-async.h"
#include "new_dynarec/new_dynarec.h"
#include "lightrec/plugin.h"
int check_unsatisfied_libcrypt(void)
{
const char *p = CdromId + 4;
+ u8 buf_sub[SUB_FRAMESIZE];
u16 id, key = 0;
+ u8 msf[3];
size_t i;
if (strncmp(CdromId, "SCE", 3) && strncmp(CdromId, "SLE", 3))
return 0;
// detected a protected game
- if (!CDR_getBufferSub(libcrypt_sectors[0]) && !sbi_sectors) {
+ lba2msf(libcrypt_sectors[0] + 150, &msf[0], &msf[1], &msf[2]);
+ if (!sbi_sectors && cdra_readSub(msf, buf_sub) != 0) {
SysPrintf("==================================================\n");
SysPrintf("LibCrypt game detected with missing SBI/subchannel\n");
SysPrintf("==================================================\n");
#include <assert.h>
#include "misc.h"
#include "cdrom.h"
+#include "cdrom-async.h"
#include "mdec.h"
#include "gpu.h"
#include "ppf.h"
s = block / 75; // seconds
d = block - s * 75; // seconds rest
- m = ((m / 10) << 4) | m % 10;
- s = ((s / 10) << 4) | s % 10;
- d = ((d / 10) << 4) | d % 10;
-
p[0] = m;
p[1] = s;
p[2] = d;
}
#define incTime() \
- time[0] = btoi(time[0]); time[1] = btoi(time[1]); time[2] = btoi(time[2]); \
time[2]++; \
if(time[2] == 75) { \
time[2] = 0; \
time[0]++; \
} \
} \
- time[0] = itob(time[0]); time[1] = itob(time[1]); time[2] = itob(time[2]);
#define READTRACK() \
- if (!CDR_readTrack(time)) return -1; \
- buf = (void *)CDR_getBuffer(); \
+ if (cdra_readTrack(time)) return -1; \
+ buf = cdra_getBuffer(); \
if (buf == NULL) return -1; \
else CheckPPFCache((u8 *)buf, time[0], time[1], time[2]);
return 0;
}
- time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
+ time[0] = 0; time[1] = 2; time[2] = 0x10;
READTRACK();
p1++;
snprintf(exename, sizeof(exename), "%s", p1);
- time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
+ time[0] = 0; time[1] = 2; time[2] = 0x10;
READTRACK();
memset(CdromId, 0, sizeof(CdromId));
memset(exename, 0, sizeof(exename));
- time[0] = itob(0);
- time[1] = itob(2);
- time[2] = itob(0x10);
+ time[0] = 0;
+ time[1] = 2;
+ time[2] = 0x10;
if (!Config.HLE && Config.SlowBoot) {
// boot to BIOS in case of CDDA or lid is open
- CDR_getStatus(&stat);
- if ((stat.Status & 0x10) || stat.Type == 2 || !CDR_readTrack(time))
+ cdra_getStatus(&stat);
+ if ((stat.Status & 0x10) || stat.Type == 2 || cdra_readTrack(time))
return 0;
}
READTRACK();
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
-u16 calcCrc(u8 *d, int len) {
+u16 calcCrc(const u8 *d, int len) {
u16 crc = 0;
int i;
int RecvPcsxInfo();
void trim(char *str);
-u16 calcCrc(u8 *d, int len);
+u16 calcCrc(const u8 *d, int len);
#ifdef __cplusplus
}
#include "plugins.h"
#include "cdriso.h"
+#include "cdrom-async.h"
#include "psxcounters.h"
static char IsoFile[MAXPATHLEN] = "";
GPUvBlank GPU_vBlank;
GPUgetScreenInfo GPU_getScreenInfo;
-CDRinit CDR_init;
-CDRshutdown CDR_shutdown;
-CDRopen CDR_open;
-CDRclose CDR_close;
-CDRtest CDR_test;
-CDRgetTN CDR_getTN;
-CDRgetTD CDR_getTD;
-CDRreadTrack CDR_readTrack;
-CDRgetBuffer CDR_getBuffer;
-CDRplay CDR_play;
-CDRstop CDR_stop;
-CDRgetStatus CDR_getStatus;
-CDRgetDriveLetter CDR_getDriveLetter;
-CDRgetBufferSub CDR_getBufferSub;
-CDRconfigure CDR_configure;
-CDRabout CDR_about;
-CDRsetfilename CDR_setfilename;
-CDRreadCDDA CDR_readCDDA;
-CDRgetTE CDR_getTE;
-CDRprefetch CDR_prefetch;
-
SPUinit SPU_init;
SPUshutdown SPU_shutdown;
SPUopen SPU_open;
return 0;
}
-void *hCDRDriver = NULL;
-
-long CALLBACK CDR__play(unsigned char *sector) { return 0; }
-long CALLBACK CDR__stop(void) { return 0; }
-
-long CALLBACK CDR__getStatus(struct CdrStat *stat) {
+int CDR__getStatus(struct CdrStat *stat) {
if (cdOpenCaseTime < 0 || cdOpenCaseTime > (s64)time(NULL))
stat->Status = 0x10;
else
return 0;
}
-char* CALLBACK CDR__getDriveLetter(void) { return NULL; }
-long CALLBACK CDR__configure(void) { return 0; }
-long CALLBACK CDR__test(void) { return 0; }
-void CALLBACK CDR__about(void) {}
-long CALLBACK CDR__setfilename(char*filename) { return 0; }
-long CALLBACK CDR__prefetch(u8 m, u8 s, u8 f) { return 1; }
-
-#define LoadCdrSym1(dest, name) \
- LoadSym(CDR_##dest, CDR##dest, name, TRUE);
-
-#define LoadCdrSym0(dest, name) \
- LoadSym(CDR_##dest, CDR##dest, name, FALSE); \
- if (CDR_##dest == NULL) CDR_##dest = (CDR##dest) CDR__##dest;
-
-#define LoadCdrSymN(dest, name) \
- LoadSym(CDR_##dest, CDR##dest, name, FALSE);
-
-static int LoadCDRplugin(const char *CDRdll) {
- void *drv;
-
- if (CDRdll == NULL) {
- cdrIsoInit();
- return 0;
- }
-
- hCDRDriver = SysLoadLibrary(CDRdll);
- if (hCDRDriver == NULL) {
- CDR_configure = NULL;
- SysMessage (_("Could not load CD-ROM plugin %s!"), CDRdll); return -1;
- }
- drv = hCDRDriver;
- LoadCdrSym1(init, "CDRinit");
- LoadCdrSym1(shutdown, "CDRshutdown");
- LoadCdrSym1(open, "CDRopen");
- LoadCdrSym1(close, "CDRclose");
- LoadCdrSym1(getTN, "CDRgetTN");
- LoadCdrSym1(getTD, "CDRgetTD");
- LoadCdrSym1(readTrack, "CDRreadTrack");
- LoadCdrSym1(getBuffer, "CDRgetBuffer");
- LoadCdrSym1(getBufferSub, "CDRgetBufferSub");
- LoadCdrSym0(play, "CDRplay");
- LoadCdrSym0(stop, "CDRstop");
- LoadCdrSym0(getStatus, "CDRgetStatus");
- LoadCdrSym0(getDriveLetter, "CDRgetDriveLetter");
- LoadCdrSym0(configure, "CDRconfigure");
- LoadCdrSym0(test, "CDRtest");
- LoadCdrSym0(about, "CDRabout");
- LoadCdrSym0(setfilename, "CDRsetfilename");
- LoadCdrSymN(readCDDA, "CDRreadCDDA");
- LoadCdrSymN(getTE, "CDRgetTE");
- LoadCdrSym0(prefetch, "CDRprefetch");
-
- return 0;
-}
-
static void *hSPUDriver = NULL;\r
static void CALLBACK SPU__registerScheduleCb(void (CALLBACK *cb)(unsigned int)) {}\r
static void CALLBACK SPU__setCDvol(unsigned char ll, unsigned char lr,
#endif
int LoadPlugins() {
- int ret;
char Plugin[MAXPATHLEN * 2];
+ int ret;
ReleasePlugins();
SysLibError();
- if (UsingIso()) {
- LoadCDRplugin(NULL);
- } else {
- sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Cdr);
- if (LoadCDRplugin(Plugin) == -1) return -1;
- }
-
sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Gpu);
if (LoadGPUplugin(Plugin) == -1) return -1;
if (LoadSIO1plugin(Plugin) == -1) return -1;
#endif
- ret = CDR_init();
+ ret = cdra_init();
if (ret < 0) { SysMessage (_("Error initializing CD-ROM plugin: %d"), ret); return -1; }
ret = GPU_init();
if (ret < 0) { SysMessage (_("Error initializing GPU plugin: %d"), ret); return -1; }
}
NetOpened = FALSE;
- if (hCDRDriver != NULL || cdrIsoActive()) CDR_shutdown();
+ cdra_shutdown();
if (hGPUDriver != NULL) GPU_shutdown();
if (hSPUDriver != NULL) SPU_shutdown();
if (hPAD1Driver != NULL) PAD1_shutdown();
if (Config.UseNet && hNETDriver != NULL) NET_shutdown();
- if (hCDRDriver != NULL) { SysCloseLibrary(hCDRDriver); hCDRDriver = NULL; }
if (hGPUDriver != NULL) { SysCloseLibrary(hGPUDriver); hGPUDriver = NULL; }
if (hSPUDriver != NULL) { SysCloseLibrary(hSPUDriver); hSPUDriver = NULL; }
if (hPAD1Driver != NULL) { SysCloseLibrary(hPAD1Driver); hPAD1Driver = NULL; }
// for CD swap
int ReloadCdromPlugin()
{
- if (hCDRDriver != NULL || cdrIsoActive()) CDR_shutdown();
- if (hCDRDriver != NULL) { SysCloseLibrary(hCDRDriver); hCDRDriver = NULL; }
-
- if (UsingIso()) {
- LoadCDRplugin(NULL);
- } else {
- char Plugin[MAXPATHLEN * 2];
- sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Cdr);
- if (LoadCDRplugin(Plugin) == -1) return -1;
- }
-
- return CDR_init();
+ cdra_shutdown();
+ return cdra_init();
}
void SetIsoFile(const char *filename) {
extern GPUvBlank GPU_vBlank;\r
extern GPUgetScreenInfo GPU_getScreenInfo;\r
\r
-// CD-ROM Functions\r
-typedef long (CALLBACK* CDRinit)(void);\r
-typedef long (CALLBACK* CDRshutdown)(void);\r
-typedef long (CALLBACK* CDRopen)(void);\r
-typedef long (CALLBACK* CDRclose)(void);\r
-typedef long (CALLBACK* CDRgetTN)(unsigned char *);\r
-typedef long (CALLBACK* CDRgetTD)(unsigned char, unsigned char *);\r
-typedef boolean (CALLBACK* CDRreadTrack)(unsigned char *);\r
-typedef unsigned char* (CALLBACK* CDRgetBuffer)(void);\r
-typedef unsigned char* (CALLBACK* CDRgetBufferSub)(int sector);\r
-typedef long (CALLBACK* CDRconfigure)(void);\r
-typedef long (CALLBACK* CDRtest)(void);\r
-typedef void (CALLBACK* CDRabout)(void);\r
-typedef long (CALLBACK* CDRplay)(unsigned char *);\r
-typedef long (CALLBACK* CDRstop)(void);\r
-typedef long (CALLBACK* CDRsetfilename)(char *);\r
+// CD-ROM\r
struct CdrStat {\r
uint32_t Type; // DATA, CDDA\r
uint32_t Status; // same as cdr.StatP\r
unsigned char Time_[3]; // unused\r
};\r
-typedef long (CALLBACK* CDRgetStatus)(struct CdrStat *);\r
-typedef char* (CALLBACK* CDRgetDriveLetter)(void);\r
-struct SubQ {\r
- char res0[12];\r
- unsigned char ControlAndADR;\r
- unsigned char TrackNumber;\r
- unsigned char IndexNumber;\r
- unsigned char TrackRelativeAddress[3];\r
- unsigned char Filler;\r
- unsigned char AbsoluteAddress[3];\r
- unsigned char CRC[2];\r
- char res1[72];\r
-};\r
-typedef long (CALLBACK* CDRreadCDDA)(unsigned char, unsigned char, unsigned char, unsigned char *);\r
-typedef long (CALLBACK* CDRgetTE)(unsigned char, unsigned char *, unsigned char *, unsigned char *);\r
-typedef long (CALLBACK* CDRprefetch)(unsigned char, unsigned char, unsigned char);\r
-\r
-// CD-ROM function pointers\r
-extern CDRinit CDR_init;\r
-extern CDRshutdown CDR_shutdown;\r
-extern CDRopen CDR_open;\r
-extern CDRclose CDR_close; \r
-extern CDRtest CDR_test;\r
-extern CDRgetTN CDR_getTN;\r
-extern CDRgetTD CDR_getTD;\r
-extern CDRreadTrack CDR_readTrack;\r
-extern CDRgetBuffer CDR_getBuffer;\r
-extern CDRgetBufferSub CDR_getBufferSub;\r
-extern CDRplay CDR_play;\r
-extern CDRstop CDR_stop;\r
-extern CDRgetStatus CDR_getStatus;\r
-extern CDRgetDriveLetter CDR_getDriveLetter;\r
-extern CDRconfigure CDR_configure;\r
-extern CDRabout CDR_about;\r
-extern CDRsetfilename CDR_setfilename;\r
-extern CDRreadCDDA CDR_readCDDA;\r
-extern CDRgetTE CDR_getTE;\r
-extern CDRprefetch CDR_prefetch;\r
\r
-long CALLBACK CDR__getStatus(struct CdrStat *stat);\r
+int CDR__getStatus(struct CdrStat *stat);\r
\r
// SPU Functions\r
typedef long (CALLBACK* SPUinit)(void); \r
void CheckPPFCache(unsigned char *pB, unsigned char m, unsigned char s, unsigned char f) {
PPF_CACHE *pcstart, *pcend, *pcpos;
- int addr = MSF2SECT(btoi(m), btoi(s), btoi(f)), pos, anz, start;
+ int addr = MSF2SECT(m, s, f), pos, anz, start;
if (ppfCache == NULL) return;
typedef struct {
char Gpu[MAXPATHLEN];
char Spu[MAXPATHLEN];
- char Cdr[MAXPATHLEN];
char Pad1[MAXPATHLEN];
char Pad2[MAXPATHLEN];
char Net[MAXPATHLEN];
boolean Mdec;
boolean PsxAuto;
boolean Cdda;
- boolean AsyncCD;
boolean CHD_Precache; /* loads disk image into memory, works with CHD only. */
boolean HLE;
boolean SlowBoot;