#include <unistd.h>
#endif
+#ifndef _WIN32
+// to enable the USE_READ_THREAD code, fix:
+// - https://github.com/notaz/pcsx_rearmed/issues/257
+// - ISOgetBufferSub to not race with async code
+//#define USE_READ_THREAD
+#endif
+
#ifdef USE_LIBRETRO_VFS
#include <streams/file_stream_transforms.h>
#undef fseeko
#ifdef HAVE_CHD
static struct {
- unsigned char (*buffer)[CD_FRAMESIZE_RAW + SUB_FRAMESIZE];
+ unsigned char *buffer;
chd_file* chd;
const chd_header* header;
unsigned int sectors_per_hunk;
- unsigned int current_hunk;
+ unsigned int current_hunk[2];
+ unsigned int current_buffer;
unsigned int sector_in_hunk;
} *chd_img;
#endif
char start[3]; // MSF-format
char length[3]; // MSF-format
FILE *handle; // for multi-track images CDDA
- unsigned int start_offset; // byte offset from start of above file
+ unsigned int start_offset; // byte offset from start of above file (chd: sector offset)
};
#define MAXTRACKS 100 /* How many tracks can a CD hold? */
if (Config.CHD_Precache && (chd_precache(chd_img->chd) != CHDERR_NONE))
goto fail_io;
- chd_img->header = chd_get_header(chd_img->chd);
+ chd_img->header = chd_get_header(chd_img->chd);
- chd_img->buffer = malloc(chd_img->header->hunkbytes);
- if (chd_img->buffer == NULL)
+ chd_img->buffer = malloc(chd_img->header->hunkbytes * 2);
+ if (chd_img->buffer == NULL)
goto fail_io;
- chd_img->sectors_per_hunk = chd_img->header->hunkbytes / (CD_FRAMESIZE_RAW + SUB_FRAMESIZE);
- chd_img->current_hunk = (unsigned int)-1;
+ chd_img->sectors_per_hunk = chd_img->header->hunkbytes / (CD_FRAMESIZE_RAW + SUB_FRAMESIZE);
+ chd_img->current_hunk[0] = (unsigned int)-1;
+ chd_img->current_hunk[1] = (unsigned int)-1;
- cddaBigEndian = TRUE;
+ cddaBigEndian = TRUE;
numtracks = 0;
memset(ti, 0, sizeof(ti));
return LoadSBI(sbiname, s);
}
-#ifdef _WIN32
+#ifndef USE_READ_THREAD
static void readThreadStop() {}
static void readThreadStart() {}
#else
}
#ifdef HAVE_CHD
+static unsigned char *chd_get_sector(unsigned int current_buffer, unsigned int sector_in_hunk)
+{
+ return chd_img->buffer
+ + current_buffer * chd_img->header->hunkbytes
+ + sector_in_hunk * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE);
+}
+
static int cdread_chd(FILE *f, unsigned int base, void *dest, int sector)
{
int hunk;
hunk = sector / chd_img->sectors_per_hunk;
chd_img->sector_in_hunk = sector % chd_img->sectors_per_hunk;
- if (hunk != chd_img->current_hunk)
+ if (hunk == chd_img->current_hunk[0])
+ chd_img->current_buffer = 0;
+ else if (hunk == chd_img->current_hunk[1])
+ chd_img->current_buffer = 1;
+ else
{
- chd_read(chd_img->chd, hunk, chd_img->buffer);
- chd_img->current_hunk = hunk;
+ chd_read(chd_img->chd, hunk, chd_img->buffer +
+ chd_img->current_buffer * chd_img->header->hunkbytes);
+ chd_img->current_hunk[chd_img->current_buffer] = hunk;
}
if (dest != cdbuffer) // copy avoid HACK
- memcpy(dest, chd_img->buffer[chd_img->sector_in_hunk],
+ 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)
{
+ unsigned int sector_in_hunk;
+ unsigned int buffer;
int hunk;
if (!subChanMixed)
return -1;
hunk = sector / chd_img->sectors_per_hunk;
- chd_img->sector_in_hunk = sector % chd_img->sectors_per_hunk;
+ sector_in_hunk = sector % chd_img->sectors_per_hunk;
- if (hunk != chd_img->current_hunk)
+ if (hunk == chd_img->current_hunk[0])
+ buffer = 0;
+ else if (hunk == chd_img->current_hunk[1])
+ buffer = 1;
+ else
{
- chd_read(chd_img->chd, hunk, chd_img->buffer);
- chd_img->current_hunk = hunk;
+ buffer = chd_img->current_buffer ^ 1;
+ chd_read(chd_img->chd, hunk, chd_img->buffer +
+ buffer * chd_img->header->hunkbytes);
+ chd_img->current_hunk[buffer] = hunk;
}
- memcpy(subbuffer, chd_img->buffer[chd_img->sector_in_hunk] + CD_FRAMESIZE_RAW, SUB_FRAMESIZE);
+ memcpy(subbuffer, chd_get_sector(buffer, sector_in_hunk) + CD_FRAMESIZE_RAW, SUB_FRAMESIZE);
return SUB_FRAMESIZE;
}
#endif
return 12*2 + ret;
}
-#ifndef _WIN32
+#ifdef USE_READ_THREAD
static int cdread_async(FILE *f, unsigned int base, void *dest, int sector) {
boolean found = FALSE;
#ifdef HAVE_CHD
static unsigned char * CALLBACK ISOgetBuffer_chd(void) {
- return chd_img->buffer[chd_img->sector_in_hunk] + 12;
+ return chd_get_sector(chd_img->current_buffer, chd_img->sector_in_hunk) + 12;
}
#endif
-#ifndef _WIN32
+#ifdef USE_READ_THREAD
static unsigned char * CALLBACK ISOgetBuffer_async(void) {
unsigned char *buffer;
pthread_mutex_lock(§orbuffer_lock);