From: notaz Date: Wed, 20 Mar 2024 23:14:56 +0000 (+0200) Subject: physical cdrom readahead X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e02164097b6a90b94305d5761d7eccd63e336490;p=pcsx_rearmed.git physical cdrom readahead much more messy than I hoped notaz/pcsx_rearmed#335 --- diff --git a/Makefile b/Makefile index 7079ecdd..8b2b87d9 100644 --- a/Makefile +++ b/Makefile @@ -249,8 +249,10 @@ OBJS += deps/libretro-common/string/stdstring.o OBJS += deps/libretro-common/vfs/vfs_implementation.o endif ifeq "$(HAVE_PHYSICAL_CDROM)" "1" -OBJS += deps/libretro-common/cdrom/cdrom.o +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 diff --git a/frontend/libretro-cdrom.c b/frontend/libretro-cdrom.c new file mode 100644 index 00000000..654de1c5 --- /dev/null +++ b/frontend/libretro-cdrom.c @@ -0,0 +1,70 @@ +#include "libretro-cdrom.h" +#include "../deps/libretro-common/cdrom/cdrom.c" +#if defined(__linux__) && !defined(ANDROID) +//#include +#endif + +static int cdrom_send_command_dummy(const libretro_vfs_implementation_file *stream, + CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, + unsigned char *sense, size_t sense_len) +{ + return 1; +} + +static int cdrom_send_command_once(const libretro_vfs_implementation_file *stream, + CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len) +{ + unsigned char sense[CDROM_MAX_SENSE_BYTES] = {0}; + int ret = +#if defined(__linux__) && !defined(ANDROID) + cdrom_send_command_linux +#elif defined(_WIN32) && !defined(_XBOX) + cdrom_send_command_win32 +#else + cdrom_send_command_dummy +#endif + (stream, dir, buf, len, cmd, cmd_len, sense, sizeof(sense)); +#ifdef CDROM_DEBUG + if (ret && sense[2]) + cdrom_print_sense_data(sense, sizeof(sense)); +#endif + (void)cdrom_send_command_dummy; + return ret; +} + +// "extensions" to libretro-common +int cdrom_set_read_speed_x(libretro_vfs_implementation_file *stream, unsigned speed) +{ + // SET CD-ROM SPEED, DA is newer? + unsigned char cmd1[] = {0xDA, 0, speed - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + unsigned char cmd2[] = {0xBB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int ret; + ret = cdrom_send_command_once(stream, DIRECTION_NONE, NULL, 0, cmd1, sizeof(cmd1)); + if (ret) { + printf("DA failed\n"); +#if defined(__linux__) && !defined(ANDROID) + // doesn't work, too late? + //ret = ioctl(fileno(stream->fp), CDROM_SELECT_SPEED, &speed); +#endif + } + if (ret) { + speed = speed * 2352 * 75 / 1024; + cmd2[2] = speed >> 8; + cmd2[3] = speed; + ret = cdrom_send_command_once(stream, DIRECTION_NONE, NULL, 0, cmd2, sizeof(cmd2)); + } + return ret; +} + +int cdrom_read_sector(libretro_vfs_implementation_file *stream, + unsigned int lba, void *b) +{ + unsigned char cmd[] = {0xBE, 0, 0, 0, 0, 0, 0, 0, 1, 0xF8, 0, 0}; + cmd[2] = lba >> 24; + cmd[3] = lba >> 16; + cmd[4] = lba >> 8; + cmd[5] = lba; + return cdrom_send_command_once(stream, DIRECTION_IN, b, 2352, cmd, sizeof(cmd)); +} + +// vim:sw=3:ts=3:expandtab diff --git a/frontend/libretro-cdrom.h b/frontend/libretro-cdrom.h new file mode 100644 index 00000000..a09f7738 --- /dev/null +++ b/frontend/libretro-cdrom.h @@ -0,0 +1,5 @@ +#include "cdrom/cdrom.h" + +int cdrom_set_read_speed_x(libretro_vfs_implementation_file *stream, unsigned speed); +int cdrom_read_sector(libretro_vfs_implementation_file *stream, + unsigned int lba, void *b); diff --git a/frontend/libretro.c b/frontend/libretro.c index a3c3610b..5cd0aee8 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -15,6 +15,7 @@ #include #endif +#include "retro_miscellaneous.h" #ifdef SWITCH #include #endif @@ -1237,12 +1238,25 @@ static void disk_init(void) } } +#ifdef HAVE_CDROM +static long CALLBACK rcdrom_open(void); +static long CALLBACK rcdrom_close(void); +#endif + static bool disk_set_eject_state(bool ejected) { // weird PCSX API.. SetCdOpenCaseTime(ejected ? -1 : (time(NULL) + 2)); LidInterrupt(); +#ifdef HAVE_CDROM + if (CDR_open == rcdrom_open) { + // likely the real cd was also changed - rescan + rcdrom_close(); + if (!ejected) + rcdrom_open(); + } +#endif disk_ejected = ejected; return true; } @@ -1295,8 +1309,7 @@ static bool disk_set_image_index(unsigned int index) if (!disk_ejected) { - SetCdOpenCaseTime(time(NULL) + 2); - LidInterrupt(); + disk_set_eject_state(disk_ejected); } disk_current_index = index; @@ -1501,23 +1514,176 @@ static void extract_directory(char *buf, const char *path, size_t size) #ifdef HAVE_CDROM #include "vfs/vfs_implementation.h" #include "vfs/vfs_implementation_cdrom.h" -#include "cdrom/cdrom.h" -static libretro_vfs_implementation_file *rcdrom_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; +} 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("cdrom_read_sector failed for lba %d\n", ret, lba); + return; + } + + 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) { - //printf("%s %s\n", __func__, GetIsoFile()); - rcdrom_h = retro_vfs_file_open_impl(GetIsoFile(), RETRO_VFS_FILE_ACCESS_READ, + 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); - return rcdrom_h ? 0 : -1; + 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) { - retro_vfs_file_close_impl(rcdrom_h); - rcdrom_h = NULL; + if (rcdrom.h) { + rcdrom_stop_thread(); + retro_vfs_file_close_impl(rcdrom.h); + rcdrom.h = NULL; } return 0; } @@ -1536,10 +1702,7 @@ 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) { - const cdrom_track_t *last = &toc->track[toc->num_tracks - 1]; - unsigned lba = cdrom_msf_to_lba(last->min, last->sec, last->frame); - lba += last->track_size; - cdrom_lba_to_msf(lba, &rt[2], &rt[1], &rt[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; @@ -1551,15 +1714,63 @@ static long CALLBACK rcdrom_getTD(unsigned char track, unsigned char *rt) 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 (lock) + slock_unlock(lock); + } + else + ret = 0; + //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) { - void *buf = ISOgetBuffer(); - int ret = -1; - if (rcdrom_h) - ret = cdrom_read(rcdrom_h, NULL, - btoi(time[0]), btoi(time[1]), btoi(time[2]), buf, 2340, 12); - //printf("%s %x:%02x:%02x -> %d\n", __func__, time[0], time[1], time[2], ret); - return !ret; + 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) @@ -1582,16 +1793,6 @@ static long CALLBACK rcdrom_getStatus(struct CdrStat *stat) stat->Type = toc->track[0].audio ? 2 : 1; return 0; } - -static long CALLBACK rcdrom_readCDDA(unsigned char m, unsigned char s, unsigned char f, - unsigned char *buffer) -{ - int ret = -1; - if (rcdrom_h) - ret = cdrom_read(rcdrom_h, NULL, m, s, f, buffer, 2352, 0); - //printf("%s %d:%02d:%02d -> %d\n", __func__, m, s, f, ret); - return ret; -} #endif // HAVE_CDROM #if defined(__QNX__) || defined(_WIN32) @@ -1851,7 +2052,8 @@ bool retro_load_game(const struct retro_game_info *info) CDR_getBufferSub = rcdrom_getBufferSub; CDR_getStatus = rcdrom_getStatus; CDR_readCDDA = rcdrom_readCDDA; -#else + CDR_prefetch = rcdrom_prefetch; +#elif !defined(USE_LIBRETRO_VFS) ReleasePlugins(); LogErr("%s\n", "Physical CD-ROM support is not compiled in."); show_notification("Physical CD-ROM support is not compiled in.", 6000, 3); @@ -2246,6 +2448,26 @@ static void update_variables(bool in_flight) display_internal_fps = true; } +#ifdef HAVE_CDROM + var.value = NULL; + var.key = "pcsx_rearmed_phys_cd_readahead"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + long newval = strtol(var.value, NULL, 10); + bool changed = rcdrom.buf_cnt != newval; + if (rcdrom.h && changed) + rcdrom_stop_thread(); + rcdrom.buf_cnt = newval; + if (rcdrom.h && changed) { + rcdrom_start_thread(); + if (rcdrom.cond && rcdrom.prefetch_lba) { + rcdrom.do_prefetch = 1; + scond_signal(rcdrom.cond); + } + } + } +#endif + // // CPU emulation related config #ifndef DRC_DISABLE diff --git a/frontend/libretro_core_options.h b/frontend/libretro_core_options.h index 3c5614e1..be9e8abf 100644 --- a/frontend/libretro_core_options.h +++ b/frontend/libretro_core_options.h @@ -182,6 +182,25 @@ struct retro_core_option_v2_definition option_defs_us[] = { "sync", }, #endif +#ifdef HAVE_CDROM +#define V(x) { #x, NULL } + { + "pcsx_rearmed_phys_cd_readahead", + "Physical 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).", + 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), + { NULL, NULL}, + }, + "12", + }, +#undef V +#endif #ifndef DRC_DISABLE { "pcsx_rearmed_drc", diff --git a/frontend/plugin.c b/frontend/plugin.c index c400165f..b3ad3bd9 100644 --- a/frontend/plugin.c +++ b/frontend/plugin.c @@ -41,6 +41,7 @@ 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; } @@ -163,6 +164,7 @@ static const struct { DIRECT_CDR(CDRsetfilename), DIRECT_CDR(CDRreadCDDA), DIRECT_CDR(CDRgetTE), + DIRECT_CDR(CDRprefetch), /* SPU */ DIRECT_SPU(SPUinit), DIRECT_SPU(SPUshutdown), diff --git a/frontend/plugin.h b/frontend/plugin.h index 5e12f902..a96d6098 100644 --- a/frontend/plugin.h +++ b/frontend/plugin.h @@ -1,7 +1,9 @@ #ifndef __PLUGIN_H__ #define __PLUGIN_H__ +#ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif #define PLUGIN_DL_BASE 0xfbad0000 diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c index 7924bb35..cd2d2026 100644 --- a/libpcsxcore/cdriso.c +++ b/libpcsxcore/cdriso.c @@ -100,6 +100,7 @@ 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 void DecodeRawSubData(void); @@ -1738,6 +1739,7 @@ void cdrIsoInit(void) { CDR_test = CDR__test; CDR_about = CDR__about; CDR_setfilename = CDR__setfilename; + CDR_prefetch = CDR__prefetch; numtracks = 0; } diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 872cc0c8..5da24c82 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -68,7 +68,7 @@ static struct { } subq; unsigned char TrackChanged; unsigned char ReportDelay; - unsigned char unused3; + unsigned char PhysCdPropagations; unsigned short sectorsRead; unsigned int freeze_ver; @@ -660,6 +660,14 @@ static void msfiSub(u8 *msfi, u32 count) void cdrPlayReadInterrupt(void) { + int hit = CDR_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); + return; + } + cdr.PhysCdPropagations = 0; + cdr.LastReadSeekCycles = psxRegs.cycle; if (cdr.Reading) { @@ -694,6 +702,7 @@ void cdrPlayReadInterrupt(void) } msfiAdd(cdr.SetSectorPlay, 1); + CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]); // update for CdlGetlocP/autopause generate_subq(cdr.SetSectorPlay); @@ -1109,6 +1118,8 @@ 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], + cdr.SetSectorPlay[2]); /* Crusaders of Might and Magic = 0.5x-4x - fix cutscene speech start @@ -1246,6 +1257,8 @@ void cdrInterrupt(void) { cdr.SubqForwardSectors = 1; cdr.sectorsRead = 0; cdr.DriveState = DRIVESTATE_SEEK; + CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], + cdr.SetSectorPlay[2]); cycles = (cdr.Mode & MODE_SPEED) ? cdReadTime : cdReadTime * 2; cycles += seekTime; @@ -1423,6 +1436,7 @@ static void cdrReadInterrupt(void) cdrReadInterruptSetResult(cdr.StatP); msfiAdd(cdr.SetSectorPlay, 1); + CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]); CDRPLAYREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime, 0); } diff --git a/libpcsxcore/plugins.c b/libpcsxcore/plugins.c index 9a399823..369ea974 100644 --- a/libpcsxcore/plugins.c +++ b/libpcsxcore/plugins.c @@ -68,6 +68,7 @@ CDRabout CDR_about; CDRsetfilename CDR_setfilename; CDRreadCDDA CDR_readCDDA; CDRgetTE CDR_getTE; +CDRprefetch CDR_prefetch; SPUinit SPU_init; SPUshutdown SPU_shutdown; @@ -257,6 +258,7 @@ 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); @@ -301,6 +303,7 @@ static int LoadCDRplugin(const char *CDRdll) { LoadCdrSym0(setfilename, "CDRsetfilename"); LoadCdrSymN(readCDDA, "CDRreadCDDA"); LoadCdrSymN(getTE, "CDRgetTE"); + LoadCdrSym0(prefetch, "CDRprefetch"); return 0; } diff --git a/libpcsxcore/plugins.h b/libpcsxcore/plugins.h index df8ed87d..4054bf67 100644 --- a/libpcsxcore/plugins.h +++ b/libpcsxcore/plugins.h @@ -133,6 +133,7 @@ struct SubQ { }; typedef long (CALLBACK* CDRreadCDDA)(unsigned char, unsigned char, unsigned char, unsigned char *); typedef long (CALLBACK* CDRgetTE)(unsigned char, unsigned char *, unsigned char *, unsigned char *); +typedef long (CALLBACK* CDRprefetch)(unsigned char, unsigned char, unsigned char); // CD-ROM function pointers extern CDRinit CDR_init; @@ -154,6 +155,7 @@ extern CDRabout CDR_about; extern CDRsetfilename CDR_setfilename; extern CDRreadCDDA CDR_readCDDA; extern CDRgetTE CDR_getTE; +extern CDRprefetch CDR_prefetch; long CALLBACK CDR__getStatus(struct CdrStat *stat);