new async cdrom + cdrom cleanup
authornotaz <notasas@gmail.com>
Wed, 2 Oct 2024 23:56:07 +0000 (02:56 +0300)
committernotaz <notasas@gmail.com>
Mon, 7 Oct 2024 22:44:18 +0000 (01:44 +0300)
Should've split this really, but that's lots of extra work...
Beware of breakage, but please report bugs.

21 files changed:
Makefile
frontend/libretro-rthreads.c [new file with mode: 0644]
frontend/libretro.c
frontend/libretro_core_options.h
frontend/main.c
frontend/menu.c
frontend/plugin.c
frontend/plugin.h
libpcsxcore/cdriso.c
libpcsxcore/cdriso.h
libpcsxcore/cdrom-async.c [new file with mode: 0644]
libpcsxcore/cdrom-async.h [new file with mode: 0644]
libpcsxcore/cdrom.c
libpcsxcore/cdrom.h
libpcsxcore/database.c
libpcsxcore/misc.c
libpcsxcore/misc.h
libpcsxcore/plugins.c
libpcsxcore/plugins.h
libpcsxcore/ppf.c
libpcsxcore/psxcommon.h

index 9c27f06..61eb95e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -48,7 +48,8 @@ CFLAGS += -DPCNT
 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 \
@@ -165,9 +166,6 @@ plugins/gpu_unai/gpulib_if.o: CFLAGS += -DREARMED -DUSE_GPULIB=1 -O3
 CC_LINK = $(CXX)
 endif
 
-# cdrcimg
-OBJS += plugins/cdrcimg/cdrcimg.o
-
 # libchdr
 #ifeq "$(HAVE_CHD)" "1"
 LCHDR = deps/libchdr
@@ -275,10 +273,13 @@ ifeq "$(HAVE_PHYSICAL_CDROM)" "1"
 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
diff --git a/frontend/libretro-rthreads.c b/frontend/libretro-rthreads.c
new file mode 100644 (file)
index 0000000..96c861d
--- /dev/null
@@ -0,0 +1,9 @@
+// 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"
index 52c2c1c..b5c3b92 100644 (file)
@@ -26,6 +26,7 @@
 #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"
@@ -1315,12 +1316,6 @@ static void disk_init(void)
    }
 }
 
-#ifdef HAVE_CDROM
-static long CALLBACK rcdrom_open(void);
-static long CALLBACK rcdrom_close(void);
-static void rcdrom_stop_thread(void);
-#endif
-
 static bool disk_set_eject_state(bool ejected)
 {
    if (ejected != disk_ejected)
@@ -1331,12 +1326,12 @@ static bool disk_set_eject_state(bool 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
@@ -1366,7 +1361,7 @@ static bool disk_set_image_index(unsigned int index)
    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..
@@ -1384,7 +1379,7 @@ static bool disk_set_image_index(unsigned int index)
       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;
@@ -1593,308 +1588,6 @@ static void extract_directory(char *buf, const char *path, size_t size)
    }
 }
 
-// raw cdrom support
-#ifdef HAVE_CDROM
-#include "vfs/vfs_implementation.h"
-#include "vfs/vfs_implementation_cdrom.h"
-#include "libretro-cdrom.h"
-#include "rthreads/rthreads.h"
-#include "retro_timers.h"
-struct cached_buf {
-   unsigned char buf[2352];
-   unsigned int lba;
-};
-static struct {
-   libretro_vfs_implementation_file *h;
-   sthread_t *thread;
-   slock_t *read_lock;
-   slock_t *buf_lock;
-   scond_t *cond;
-   struct cached_buf *buf;
-   unsigned int buf_cnt, thread_exit, do_prefetch;
-   unsigned int total_lba, prefetch_lba;
-   int check_eject_delay;
-} rcdrom;
-
-static void lbacache_do(unsigned int lba)
-{
-   unsigned char m, s, f, buf[2352];
-   unsigned int i = lba % rcdrom.buf_cnt;
-   int ret;
-
-   cdrom_lba_to_msf(lba + 150, &m, &s, &f);
-   slock_lock(rcdrom.read_lock);
-   ret = cdrom_read_sector(rcdrom.h, lba, buf);
-   slock_lock(rcdrom.buf_lock);
-   slock_unlock(rcdrom.read_lock);
-   //printf("%d:%02d:%02d m%d f%d\n", m, s, f, buf[12+3], ((buf[12+4+2] >> 5) & 1) + 1);
-   if (ret) {
-      rcdrom.do_prefetch = 0;
-      slock_unlock(rcdrom.buf_lock);
-      LogErr("prefetch: cdrom_read_sector failed for lba %d\n", lba);
-      return;
-   }
-   rcdrom.check_eject_delay = 100;
-
-   if (lba != rcdrom.buf[i].lba) {
-      memcpy(rcdrom.buf[i].buf, buf, sizeof(rcdrom.buf[i].buf));
-      rcdrom.buf[i].lba = lba;
-   }
-   slock_unlock(rcdrom.buf_lock);
-   retro_sleep(0); // why does the main thread stall without this?
-}
-
-static int lbacache_get(unsigned int lba, void *buf)
-{
-   unsigned int i;
-   int ret = 0;
-
-   i = lba % rcdrom.buf_cnt;
-   slock_lock(rcdrom.buf_lock);
-   if (lba == rcdrom.buf[i].lba) {
-      memcpy(buf, rcdrom.buf[i].buf, 2352);
-      ret = 1;
-   }
-   slock_unlock(rcdrom.buf_lock);
-   return ret;
-}
-
-static void rcdrom_prefetch_thread(void *unused)
-{
-   unsigned int buf_cnt, lba, lba_to;
-
-   slock_lock(rcdrom.buf_lock);
-   while (!rcdrom.thread_exit)
-   {
-#ifdef __GNUC__
-      __asm__ __volatile__("":::"memory"); // barrier
-#endif
-      if (!rcdrom.do_prefetch)
-         scond_wait(rcdrom.cond, rcdrom.buf_lock);
-      if (!rcdrom.do_prefetch || !rcdrom.h || rcdrom.thread_exit)
-         continue;
-
-      buf_cnt = rcdrom.buf_cnt;
-      lba = rcdrom.prefetch_lba;
-      lba_to = lba + buf_cnt;
-      if (lba_to > rcdrom.total_lba)
-         lba_to = rcdrom.total_lba;
-      for (; lba < lba_to; lba++) {
-         if (lba != rcdrom.buf[lba % buf_cnt].lba)
-            break;
-      }
-      if (lba == lba_to) {
-         // caching complete
-         rcdrom.do_prefetch = 0;
-         continue;
-      }
-
-      slock_unlock(rcdrom.buf_lock);
-      lbacache_do(lba);
-      slock_lock(rcdrom.buf_lock);
-   }
-   slock_unlock(rcdrom.buf_lock);
-}
-
-static void rcdrom_stop_thread(void)
-{
-   rcdrom.thread_exit = 1;
-   if (rcdrom.buf_lock) {
-      slock_lock(rcdrom.buf_lock);
-      rcdrom.do_prefetch = 0;
-      if (rcdrom.cond)
-         scond_signal(rcdrom.cond);
-      slock_unlock(rcdrom.buf_lock);
-   }
-   if (rcdrom.thread) {
-      sthread_join(rcdrom.thread);
-      rcdrom.thread = NULL;
-   }
-   if (rcdrom.cond) { scond_free(rcdrom.cond); rcdrom.cond = NULL; }
-   if (rcdrom.buf_lock) { slock_free(rcdrom.buf_lock); rcdrom.buf_lock = NULL; }
-   if (rcdrom.read_lock) { slock_free(rcdrom.read_lock); rcdrom.read_lock = NULL; }
-   free(rcdrom.buf);
-   rcdrom.buf = NULL;
-}
-
-// the thread is optional, if anything fails we can do direct reads
-static void rcdrom_start_thread(void)
-{
-   rcdrom_stop_thread();
-   rcdrom.thread_exit = rcdrom.prefetch_lba = rcdrom.do_prefetch = 0;
-   if (rcdrom.buf_cnt == 0)
-      return;
-   rcdrom.buf = calloc(rcdrom.buf_cnt, sizeof(rcdrom.buf[0]));
-   rcdrom.buf_lock = slock_new();
-   rcdrom.read_lock = slock_new();
-   rcdrom.cond = scond_new();
-   if (rcdrom.buf && rcdrom.buf_lock && rcdrom.read_lock && rcdrom.cond) {
-      rcdrom.thread = sthread_create(rcdrom_prefetch_thread, NULL);
-      rcdrom.buf[0].lba = ~0;
-   }
-   if (!rcdrom.thread) {
-      LogErr("cdrom precache thread init failed.\n");
-      rcdrom_stop_thread();
-   }
-}
-
-static long CALLBACK rcdrom_open(void)
-{
-   const char *name = GetIsoFile();
-   //printf("%s %s\n", __func__, name);
-   rcdrom.h = retro_vfs_file_open_impl(name, RETRO_VFS_FILE_ACCESS_READ,
-      RETRO_VFS_FILE_ACCESS_HINT_NONE);
-   if (rcdrom.h) {
-      int ret = cdrom_set_read_speed_x(rcdrom.h, 4);
-      if (ret) LogErr("CD speed set failed\n");
-      const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc();
-      const cdrom_track_t *last = &toc->track[toc->num_tracks - 1];
-      unsigned int lba = cdrom_msf_to_lba(last->min, last->sec, last->frame) - 150;
-      rcdrom.total_lba = lba + last->track_size;
-      //cdrom_get_current_config_random_readable(rcdrom.h);
-      //cdrom_get_current_config_multiread(rcdrom.h);
-      //cdrom_get_current_config_cdread(rcdrom.h);
-      //cdrom_get_current_config_profiles(rcdrom.h);
-      rcdrom_start_thread();
-      return 0;
-   }
-   LogErr("retro_vfs_file_open failed for '%s'\n", name);
-   return -1;
-}
-
-static long CALLBACK rcdrom_close(void)
-{
-   //printf("%s\n", __func__);
-   if (rcdrom.h) {
-      rcdrom_stop_thread();
-      retro_vfs_file_close_impl(rcdrom.h);
-      rcdrom.h = NULL;
-   }
-   return 0;
-}
-
-static long CALLBACK rcdrom_getTN(unsigned char *tn)
-{
-   const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc();
-   tn[0] = 1;
-   tn[1] = toc->num_tracks;
-   //printf("%s -> %d %d\n", __func__, tn[0], tn[1]);
-   return 0;
-}
-
-static long CALLBACK rcdrom_getTD(unsigned char track, unsigned char *rt)
-{
-   const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc();
-   rt[0] = 0, rt[1] = 2, rt[2] = 0;
-   if (track == 0) {
-      cdrom_lba_to_msf(rcdrom.total_lba + 150, &rt[2], &rt[1], &rt[0]);
-   }
-   else if (track <= toc->num_tracks) {
-      int i = track - 1;
-      rt[2] = toc->track[i].min;
-      rt[1] = toc->track[i].sec;
-      rt[0] = toc->track[i].frame;
-   }
-   //printf("%s %d -> %d:%02d:%02d\n", __func__, track, rt[2], rt[1], rt[0]);
-   return 0;
-}
-
-static long CALLBACK rcdrom_prefetch(unsigned char m, unsigned char s, unsigned char f)
-{
-   unsigned int lba = cdrom_msf_to_lba(m, s, f) - 150;
-   if (rcdrom.cond && rcdrom.h) {
-      rcdrom.prefetch_lba = lba;
-      rcdrom.do_prefetch = 1;
-      scond_signal(rcdrom.cond);
-   }
-   if (rcdrom.buf) {
-     unsigned int c = rcdrom.buf_cnt;
-     if (c)
-        return rcdrom.buf[lba % c].lba == lba;
-   }
-   return 1;
-}
-
-static int rcdrom_read_msf(unsigned char m, unsigned char s, unsigned char f,
-      void *buf, const char *func)
-{
-   unsigned int lba = cdrom_msf_to_lba(m, s, f) - 150;
-   int hit = 0, ret = -1;
-   if (rcdrom.buf_lock)
-      hit = lbacache_get(lba, buf);
-   if (!hit && rcdrom.read_lock) {
-      // maybe still prefetching
-      slock_lock(rcdrom.read_lock);
-      slock_unlock(rcdrom.read_lock);
-      hit = lbacache_get(lba, buf);
-      if (hit)
-         hit = 2;
-   }
-   if (!hit) {
-      slock_t *lock = rcdrom.read_lock;
-      rcdrom.do_prefetch = 0;
-      if (lock)
-         slock_lock(lock);
-      if (rcdrom.h) {
-         ret = cdrom_read_sector(rcdrom.h, lba, buf);
-         if (ret)
-            LogErr("cdrom_read_sector failed for lba %d\n", lba);
-      }
-      if (lock)
-         slock_unlock(lock);
-   }
-   else
-      ret = 0;
-   rcdrom.check_eject_delay = ret ? 0 : 100;
-   //printf("%s %d:%02d:%02d -> %d hit %d\n", func, m, s, f, ret, hit);
-   return ret;
-}
-
-static boolean CALLBACK rcdrom_readTrack(unsigned char *time)
-{
-   unsigned char m = btoi(time[0]), s = btoi(time[1]), f = btoi(time[2]);
-   return !rcdrom_read_msf(m, s, f, ISOgetBuffer() - 12, __func__);
-}
-
-static long CALLBACK rcdrom_readCDDA(unsigned char m, unsigned char s, unsigned char f,
-      unsigned char *buffer)
-{
-   return rcdrom_read_msf(m, s, f, buffer, __func__);
-}
-
-static unsigned char * CALLBACK rcdrom_getBuffer(void)
-{
-   //printf("%s\n", __func__);
-   return ISOgetBuffer();
-}
-
-static unsigned char * CALLBACK rcdrom_getBufferSub(int sector)
-{
-   //printf("%s %d %d\n", __func__, sector, rcdrom_h->cdrom.last_frame_lba);
-   return NULL;
-}
-
-static long CALLBACK rcdrom_getStatus(struct CdrStat *stat)
-{
-   const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc();
-   //printf("%s %p\n", __func__, stat);
-   CDR__getStatus(stat);
-   stat->Type = toc->track[0].audio ? 2 : 1;
-   return 0;
-}
-
-static void rcdrom_check_eject(void)
-{
-   bool media_inserted;
-   if (!rcdrom.h || rcdrom.do_prefetch || rcdrom.check_eject_delay-- > 0)
-      return;
-   rcdrom.check_eject_delay = 100;
-   media_inserted = cdrom_is_media_inserted(rcdrom.h); // 1-2ms
-   if (!media_inserted != disk_ejected)
-      disk_set_eject_state(!media_inserted);
-}
-#endif // HAVE_CDROM
-
 #if defined(__QNX__) || defined(_WIN32)
 /* Blackberry QNX doesn't have strcasestr */
 
@@ -2147,18 +1840,7 @@ bool retro_load_game(const struct retro_game_info *info)
    }
    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);
@@ -2233,7 +1915,7 @@ bool retro_load_game(const struct retro_game_info *info)
             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;
@@ -2567,23 +2249,12 @@ static void update_variables(bool in_flight)
          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
 
@@ -3585,8 +3256,12 @@ void retro_run(void)
    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
 }
 
index 47a3ed4..86fe783 100644 (file)
@@ -180,19 +180,29 @@ struct retro_core_option_v2_definition option_defs_us[] = {
       "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",
index 4c051e2..61dbf63 100644 (file)
@@ -25,6 +25,7 @@
 #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"
@@ -66,7 +67,7 @@ enum sched_action emu_action, emu_action_old;
 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);
@@ -95,21 +96,7 @@ static int get_gameid_filename(char *buf, int size, const char *fmt, int i) {
 
 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)
@@ -124,7 +111,6 @@ 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");
@@ -819,9 +805,6 @@ void SysReset() {
        // reset can run code, timing must be set
        pl_timing_prepare(Config.PsxType);
 
-       // hmh core forgets this
-       CDR_stop();
-   
        EmuReset();
 
        GPU_updateLace = real_lace;
@@ -946,7 +929,7 @@ static int _OpenPlugins(void) {
        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; }
@@ -960,64 +943,6 @@ static int _OpenPlugins(void) {
        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;
 }
 
@@ -1040,32 +965,25 @@ void ClosePlugins() {
        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) {
index 15034a9..275028c 100644 (file)
@@ -38,6 +38,7 @@
 #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"
@@ -2285,7 +2286,7 @@ static int swap_cd_image(void)
                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;
        }
@@ -2303,8 +2304,8 @@ static int swap_cd_multidisk(void)
        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;
        }
@@ -2759,11 +2760,6 @@ void menu_prepare_emu(void)
        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);
 
index b3ad3bd..1914325 100644 (file)
 #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; }
 
@@ -134,7 +111,6 @@ extern void GPUrearmedCallbacks(const struct rearmed_cbs *cbs);
 #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)
@@ -144,27 +120,6 @@ static const struct {
        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),
@@ -230,9 +185,6 @@ void *plugin_link(enum builtint_plugins_e id, const char *sym)
 {
        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;
index a96d609..996da55 100644 (file)
@@ -10,9 +10,7 @@
 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);
index 243c036..ff20731 100644 (file)
  ***************************************************************************/
 
 #include "psxcommon.h"
-#include "plugins.h"
 #include "cdrom.h"
 #include "cdriso.h"
 #include "ppf.h"
 
+#include <errno.h>
+#include <zlib.h>
+#ifdef HAVE_CHD
+#include <libchdr/chd.h>
+#endif
+
 #ifdef _WIN32
 #define strcasecmp _stricmp
 #else
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#if P_HAVE_PTHREAD
-#include <pthread.h>
-#include <sys/time.h>
-#endif
 #endif
-#include <errno.h>
-#include <zlib.h>
 
-#ifdef HAVE_CHD
-#include "libchdr/chd.h"
+#ifdef USE_LIBRETRO_VFS
+#include <streams/file_stream_transforms.h>
+#undef fseeko
+#undef ftello
+#undef rewind
+#define ftello rftell
+#define fseeko rfseek
+#define rewind(f_) rfseek(f_, 0, SEEK_SET)
 #endif
 
 #define OFF_T_MSB ((off_t)1 << (sizeof(off_t) * 8 - 1))
@@ -58,7 +63,6 @@ static boolean subChanRaw = FALSE;
 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.
@@ -93,16 +97,9 @@ static struct {
 #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;
@@ -118,11 +115,13 @@ static int numtracks = 0;
 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;
@@ -1071,7 +1070,7 @@ static int opensbifile(const char *isoname) {
                        strcpy(sbiname + strlen(sbiname) - 4, disknum);
                }
                else
-               strcpy(sbiname + strlen(sbiname) - 4, ".sbi");
+                       strcpy(sbiname + strlen(sbiname) - 4, ".sbi");
        }
        else {
                return -1;
@@ -1087,6 +1086,8 @@ 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);
@@ -1106,6 +1107,8 @@ static int cdread_sub_mixed(FILE *f, unsigned int base, void *dest, int sector)
 
        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);
@@ -1118,16 +1121,16 @@ fail_io:
        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);
@@ -1208,7 +1211,7 @@ static int cdread_compressed(FILE *f, unsigned int base, void *dest, int 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;
        }
@@ -1231,7 +1234,7 @@ static int cdread_compressed(FILE *f, unsigned int base, void *dest, int sector)
        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;
@@ -1265,13 +1268,13 @@ static int cdread_chd(FILE *f, unsigned int base, void *dest, int sector)
                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;
@@ -1295,41 +1298,48 @@ static int cdread_sub_chd(FILE *f, int sector)
                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;
 }
 
-static unsigned char * CALLBACK ISOgetBuffer_compr(void) {
-       return compr_img->buff_raw[compr_img->sector_in_blk] + 12;
+static void * ISOgetBuffer_normal(void) {
+       return cdbuffer + 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
 
-unsigned char * CALLBACK ISOgetBuffer(void) {
-       return cdbuffer + 12;
-}
+void * (*ISOgetBuffer)(void) = ISOgetBuffer_normal;
 
 static void PrintTracks(void) {
        int i;
@@ -1345,7 +1355,8 @@ static void PrintTracks(void) {
 
 // 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;
@@ -1356,16 +1367,16 @@ static long CALLBACK ISOopen(void) {
                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;
@@ -1374,36 +1385,36 @@ static long CALLBACK ISOopen(void) {
        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);
@@ -1411,15 +1422,15 @@ static long CALLBACK ISOopen(void) {
        }
 #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;
@@ -1473,7 +1484,8 @@ static long CALLBACK ISOopen(void) {
        return 0;
 }
 
-static long CALLBACK ISOclose(void) {
+int ISOclose(void)
+{
        int i;
 
        if (cdHandle != NULL) {
@@ -1491,7 +1503,7 @@ static long CALLBACK ISOclose(void) {
                free(compr_img);
                compr_img = NULL;
        }
-       
+
 #ifdef HAVE_CHD
        if (chd_img != NULL) {
                chd_close(chd_img->chd);
@@ -1512,28 +1524,31 @@ static long CALLBACK ISOclose(void) {
        UnloadSBI();
 
        memset(cdbuffer, 0, sizeof(cdbuffer));
-       CDR_getBuffer = ISOgetBuffer;
+       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) {
@@ -1548,23 +1563,18 @@ static long CALLBACK ISOgetTN(unsigned char *buffer) {
 
 // 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;
@@ -1576,7 +1586,7 @@ static long CALLBACK ISOgetTD(unsigned char track, unsigned char *buffer) {
 }
 
 // decode 'raw' subchannel data ripped by cdrdao
-static void DecodeRawSubData(void) {
+static void DecodeRawSubData(unsigned char *subbuffer) {
        unsigned char subQData[12];
        int i;
 
@@ -1592,64 +1602,68 @@ static void DecodeRawSubData(void) {
 }
 
 // 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)
@@ -1659,14 +1673,14 @@ static long CALLBACK ISOgetStatus(struct CdrStat *stat) {
 }
 
 // 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--) {
@@ -1679,8 +1693,8 @@ long CALLBACK ISOreadCDDA(unsigned char m, unsigned char s, unsigned char f, uns
 
        // 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) {
@@ -1693,57 +1707,32 @@ long CALLBACK ISOreadCDDA(unsigned char m, unsigned char s, unsigned char f, uns
                        }
                }
        }
-       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;
 }
index 079e0b8..ed79d60 100644 (file)
 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;
diff --git a/libpcsxcore/cdrom-async.c b/libpcsxcore/cdrom-async.c
new file mode 100644 (file)
index 0000000..026a345
--- /dev/null
@@ -0,0 +1,566 @@
+/***************************************************************************
+ *   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
diff --git a/libpcsxcore/cdrom-async.h b/libpcsxcore/cdrom-async.h
new file mode 100644 (file)
index 0000000..02fe6b7
--- /dev/null
@@ -0,0 +1,29 @@
+
+#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
index 335c2dc..516ca8e 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <assert.h>
 #include "cdrom.h"
+#include "cdrom-async.h"
 #include "misc.h"
 #include "ppf.h"
 #include "psxdma.h"
@@ -125,6 +126,18 @@ static struct {
 } 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
@@ -238,19 +251,6 @@ static unsigned int msf2sec(const u8 *msf) {
        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; \
@@ -269,7 +269,6 @@ static void sec2msf(unsigned int s, u8 *msf) {
 }
 
 #define StopCdda() { \
-       if (cdr.Play && !Config.Cdda) CDR_stop(); \
        cdr.Play = FALSE; \
        cdr.FastForward = 0; \
        cdr.FastBackward = 0; \
@@ -327,7 +326,7 @@ void cdrLidSeekInterrupt(void)
                //StopReading();
                SetPlaySeekRead(cdr.StatP, 0);
 
-               if (CDR_getStatus(&cdr_stat) == -1)
+               if (cdra_getStatus(&cdr_stat) == -1)
                        return;
 
                if (cdr_stat.Status & STATUS_SHELLOPEN)
@@ -339,7 +338,7 @@ void cdrLidSeekInterrupt(void)
                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
@@ -412,8 +411,8 @@ static void Find_CurTrack(const u8 *time)
        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;
        }
@@ -425,22 +424,20 @@ static void generate_subq(const u8 *time)
        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;
 
@@ -457,7 +454,8 @@ static void generate_subq(const u8 *time)
                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]);
@@ -470,41 +468,37 @@ static void generate_subq(const u8 *time)
 
 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",
@@ -669,7 +663,7 @@ static int msfiEq(const u8 *a, const u8 *b)
 
 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);
@@ -699,7 +693,7 @@ void cdrPlayReadInterrupt(void)
                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)))
@@ -711,7 +705,7 @@ void cdrPlayReadInterrupt(void)
        }
 
        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);
@@ -721,7 +715,7 @@ void cdrPlayReadInterrupt(void)
 
 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;
@@ -753,7 +747,6 @@ void cdrInterrupt(void) {
        u32 second_resp_time = 0;
        const void *buf;
        u8 ParamC;
-       u8 set_loc[3];
        int read_ok;
        u16 not_ready = 0;
        u8 IrqStat = Acknowledge;
@@ -768,7 +761,7 @@ void cdrInterrupt(void) {
        }
        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);
@@ -833,6 +826,7 @@ void cdrInterrupt(void) {
                        }
                        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))
@@ -866,11 +860,9 @@ void cdrInterrupt(void) {
 
                                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) {
@@ -903,9 +895,6 @@ void cdrInterrupt(void) {
                        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
@@ -950,11 +939,8 @@ void cdrInterrupt(void) {
                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();
@@ -1097,7 +1083,7 @@ void cdrInterrupt(void) {
                        break;
 
                case CdlGetTN:
-                       if (CDR_getTN(cdr.ResultTN) == -1) {
+                       if (cdra_getTN(cdr.ResultTN) != 0) {
                                assert(0);
                        }
                        SetResultSize_(3);
@@ -1107,15 +1093,15 @@ void cdrInterrupt(void) {
 
                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:
@@ -1128,7 +1114,7 @@ void cdrInterrupt(void) {
                                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
@@ -1155,7 +1141,7 @@ void cdrInterrupt(void) {
 
                        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;
@@ -1193,7 +1179,7 @@ void cdrInterrupt(void) {
                        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 {
@@ -1267,7 +1253,7 @@ void cdrInterrupt(void) {
                        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;
@@ -1385,7 +1371,7 @@ static void cdrReadInterrupt(void)
 
        read_ok = ReadTrack(cdr.SetSectorPlay);
        if (read_ok)
-               buf = CDR_getBuffer();
+               buf = cdra_getBuffer();
        if (buf == NULL)
                read_ok = 0;
 
@@ -1448,7 +1434,7 @@ static void cdrReadInterrupt(void)
                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);
 }
@@ -1750,13 +1736,8 @@ void cdrDmaInterrupt(void)
 
 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() {
@@ -1781,10 +1762,7 @@ int cdrFreeze(void *f, int Mode) {
        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) {
@@ -1804,9 +1782,12 @@ int cdrFreeze(void *f, int Mode) {
                        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);
 
@@ -1815,8 +1796,6 @@ int cdrFreeze(void *f, int Mode) {
                                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,
index ee0b4d4..b8682b0 100644 (file)
@@ -38,13 +38,21 @@ extern "C" {
 #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);
index 2e382e3..c05b80c 100644 (file)
@@ -1,6 +1,7 @@
 #include "misc.h"
 #include "sio.h"
 #include "ppf.h"
+#include "cdrom-async.h"
 #include "new_dynarec/new_dynarec.h"
 #include "lightrec/plugin.h"
 
@@ -274,7 +275,9 @@ static const u16 libcrypt_sectors[16] = {
 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))
@@ -289,7 +292,8 @@ int check_unsatisfied_libcrypt(void)
                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");
index d4c886f..68982ab 100644 (file)
@@ -26,6 +26,7 @@
 #include <assert.h>
 #include "misc.h"
 #include "cdrom.h"
+#include "cdrom-async.h"
 #include "mdec.h"
 #include "gpu.h"
 #include "ppf.h"
@@ -71,17 +72,12 @@ static void mmssdd( char *b, char *p )
        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; \
@@ -91,11 +87,10 @@ static void mmssdd( char *b, char *p )
                        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]);
 
@@ -216,7 +211,7 @@ int LoadCdrom() {
                        return 0;
        }
 
-       time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
+       time[0] = 0; time[1] = 2; time[2] = 0x10;
 
        READTRACK();
 
@@ -320,7 +315,7 @@ int LoadCdromFile(const char *filename, EXE_HEADER *head, u8 *time_bcd_out) {
                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();
 
@@ -374,14 +369,14 @@ int CheckCdrom() {
        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();
@@ -967,7 +962,7 @@ static unsigned short crctab[256] = {
        0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
 };
 
-u16 calcCrc(u8 *d, int len) {
+u16 calcCrc(const u8 *d, int len) {
        u16 crc = 0;
        int i;
 
index 22245d8..303af7b 100644 (file)
@@ -72,7 +72,7 @@ int SendPcsxInfo();
 int RecvPcsxInfo();
 
 void trim(char *str);
-u16 calcCrc(u8 *d, int len);
+u16 calcCrc(const u8 *d, int len);
 
 #ifdef __cplusplus
 }
index 369ea97..e59e8c6 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "plugins.h"
 #include "cdriso.h"
+#include "cdrom-async.h"
 #include "psxcounters.h"
 
 static char IsoFile[MAXPATHLEN] = "";
@@ -49,27 +50,6 @@ GPUshowScreenPic      GPU_showScreenPic;
 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;
@@ -239,12 +219,7 @@ static int LoadGPUplugin(const char *GPUdll) {
        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
@@ -253,61 +228,6 @@ long CALLBACK CDR__getStatus(struct CdrStat *stat) {
        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,
@@ -1161,19 +1081,12 @@ static int LoadSIO1plugin(const char *SIO1dll) {
 #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;
 
@@ -1199,7 +1112,7 @@ int LoadPlugins() {
        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; }
@@ -1231,7 +1144,7 @@ void ReleasePlugins() {
        }
        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();
@@ -1239,7 +1152,6 @@ void ReleasePlugins() {
 
        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; }
@@ -1261,18 +1173,8 @@ void ReleasePlugins() {
 // 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) {
index 4054bf6..b2efbce 100644 (file)
@@ -97,67 +97,14 @@ extern GPUshowScreenPic GPU_showScreenPic;
 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
index 6a88e05..3dcf416 100644 (file)
@@ -94,7 +94,7 @@ void FreePPFCache() {
 
 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;
 
index 0a0bd86..68c32a9 100644 (file)
@@ -117,7 +117,6 @@ void __Log(char *fmt, ...);
 typedef struct {
        char Gpu[MAXPATHLEN];
        char Spu[MAXPATHLEN];
-       char Cdr[MAXPATHLEN];
        char Pad1[MAXPATHLEN];
        char Pad2[MAXPATHLEN];
        char Net[MAXPATHLEN];
@@ -132,7 +131,6 @@ typedef struct {
        boolean Mdec;
        boolean PsxAuto;
        boolean Cdda;
-       boolean AsyncCD;
        boolean CHD_Precache; /* loads disk image into memory, works with CHD only. */
        boolean HLE;
        boolean SlowBoot;