#include <process.h>
#include <windows.h>
#define strcasecmp _stricmp
-#define usleep(x) Sleep((x) / 1000)
-#else
+#elif P_HAVE_PTHREAD
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
static boolean subChanMixed = FALSE;
static boolean subChanRaw = FALSE;
-static boolean subChanMissing = FALSE;
static boolean multifile = FALSE;
#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
-int (*cdimg_read_func)(FILE *f, unsigned int base, void *dest, int sector);
+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);
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? */
off_t psisoimg_offs, cdimg_base;
unsigned int t, cd_length;
unsigned int offsettab[8];
+ unsigned int psar_offs, index_entry_size, index_entry_offset;
const char *ext = NULL;
int i, ret;
goto fail_io;
}
- ret = fseeko(cdHandle, pbp_hdr.psar_offs, SEEK_SET);
+ psar_offs = SWAP32(pbp_hdr.psar_offs);
+
+ ret = fseeko(cdHandle, psar_offs, SEEK_SET);
if (ret != 0) {
- SysPrintf("failed to seek to %x\n", pbp_hdr.psar_offs);
+ SysPrintf("failed to seek to %x\n", psar_offs);
goto fail_io;
}
- psisoimg_offs = pbp_hdr.psar_offs;
+ psisoimg_offs = psar_offs;
if (fread(psar_sig, 1, sizeof(psar_sig), cdHandle) != sizeof(psar_sig))
goto fail_io;
psar_sig[10] = 0;
if (strcmp(psar_sig, "PSTITLEIMG") == 0) {
// multidisk image?
- ret = fseeko(cdHandle, pbp_hdr.psar_offs + 0x200, SEEK_SET);
+ ret = fseeko(cdHandle, psar_offs + 0x200, SEEK_SET);
if (ret != 0) {
- SysPrintf("failed to seek to %x\n", pbp_hdr.psar_offs + 0x200);
+ SysPrintf("failed to seek to %x\n", psar_offs + 0x200);
goto fail_io;
}
if (cdrIsoMultidiskSelect >= cdrIsoMultidiskCount)
cdrIsoMultidiskSelect = 0;
- psisoimg_offs += offsettab[cdrIsoMultidiskSelect];
+ psisoimg_offs += SWAP32(offsettab[cdrIsoMultidiskSelect]);
ret = fseeko(cdHandle, psisoimg_offs, SEEK_SET);
if (ret != 0) {
goto fail_index;
}
- if (index_entry.size == 0)
+ index_entry_size = SWAP32(index_entry.size);
+ index_entry_offset = SWAP32(index_entry.offset);
+
+ if (index_entry_size == 0)
break;
- compr_img->index_table[i] = cdimg_base + index_entry.offset;
+ compr_img->index_table[i] = cdimg_base + index_entry_offset;
}
- compr_img->index_table[i] = cdimg_base + index_entry.offset + index_entry.size;
+ compr_img->index_table[i] = cdimg_base + index_entry_offset + index_entry_size;
return 0;
#ifdef HAVE_CHD
static int handlechd(const char *isofile) {
- int frame_offset = 0;
+ int frame_offset = 150;
int file_offset = 0;
chd_img = calloc(1, sizeof(*chd_img));
chd_img->header = chd_get_header(chd_img->chd);
- chd_img->buffer = malloc(chd_img->header->hunkbytes);
+ 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->current_hunk[0] = (unsigned int)-1;
+ chd_img->current_hunk[1] = (unsigned int)-1;
cddaBigEndian = TRUE;
SysPrintf("chd: %s\n", meta);
if (md.track == 1) {
- md.pregap = 150;
if (!strncmp(md.subtype, "RW", 2)) {
subChanMixed = TRUE;
if (!strcmp(md.subtype, "RW_RAW"))
subChanRaw = TRUE;
}
}
- else
- sec2msf(msf2sec(ti[md.track-1].length) + md.pregap, ti[md.track-1].length);
ti[md.track].type = !strncmp(md.type, "AUDIO", 5) ? CDDA : DATA;
sec2msf(frame_offset + md.pregap, ti[md.track].start);
sec2msf(md.frames, ti[md.track].length);
- ti[md.track].start_offset = file_offset;
+ ti[md.track].start_offset = file_offset + md.pregap;
- frame_offset += md.pregap + md.frames + md.postgap;
- file_offset += md.frames + md.postgap;
+ // XXX: what about postgap?
+ frame_offset += md.frames;
+ file_offset += md.frames;
numtracks++;
}
static int cdread_normal(FILE *f, unsigned int base, void *dest, int sector)
{
- fseek(f, base + sector * CD_FRAMESIZE_RAW, SEEK_SET);
- return fread(dest, 1, CD_FRAMESIZE_RAW, f);
+ int ret;
+ if (fseek(f, base + sector * CD_FRAMESIZE_RAW, SEEK_SET))
+ goto fail_io;
+ ret = fread(dest, 1, CD_FRAMESIZE_RAW, f);
+ if (ret <= 0)
+ goto fail_io;
+ return ret;
+
+fail_io:
+ // often happens in cdda gaps of a split cue/bin, so not logged
+ //SysPrintf("File IO error %d, base %u, sector %u\n", errno, base, sector);
+ return -1;
}
static int cdread_sub_mixed(FILE *f, unsigned int base, void *dest, int sector)
{
int ret;
- fseek(f, base + sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET);
+ if (fseek(f, base + sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET))
+ goto fail_io;
ret = fread(dest, 1, CD_FRAMESIZE_RAW, f);
+ if (ret <= 0)
+ goto fail_io;
+ return ret;
+
+fail_io:
+ //SysPrintf("File IO error %d, base %u, sector %u\n", errno, base, sector);
+ return -1;
+}
+
+static int cdread_sub_sub_mixed(FILE *f, int sector)
+{
+ if (fseek(f, sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE) + CD_FRAMESIZE_RAW, SEEK_SET))
+ goto fail_io;
if (fread(subbuffer, 1, SUB_FRAMESIZE, f) != SUB_FRAMESIZE)
goto fail_io;
- if (subChanRaw) DecodeRawSubData();
- goto done;
+ return SUB_FRAMESIZE;
fail_io:
-#ifndef NDEBUG
- SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
-#endif
-
-done:
- return ret;
+ SysPrintf("subchannel: file IO error %d, sector %u\n", errno, sector);
+ return -1;
}
static int uncompress2_pcsx(void *out, unsigned long *out_size, void *in, unsigned long in_size)
}
#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;
- if (base)
- sector += base;
+ sector += base;
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);
- if (subChanMixed) {
- memcpy(subbuffer, chd_img->buffer[chd_img->sector_in_hunk] + CD_FRAMESIZE_RAW,
- SUB_FRAMESIZE);
- if (subChanRaw)
- DecodeRawSubData();
- }
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;
+ sector_in_hunk = sector % chd_img->sectors_per_hunk;
+
+ if (hunk == chd_img->current_hunk[0])
+ buffer = 0;
+ else if (hunk == chd_img->current_hunk[1])
+ buffer = 1;
+ else
+ {
+ 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_get_sector(buffer, sector_in_hunk) + CD_FRAMESIZE_RAW, SUB_FRAMESIZE);
+ return SUB_FRAMESIZE;
+}
#endif
static int cdread_2048(FILE *f, unsigned int base, void *dest, int sector)
sec2msf(sector + 2 * 75, (char *)&cdbuffer[12]);
cdbuffer[12 + 3] = 1;
- return ret;
+ return 12*2 + ret;
}
static unsigned char * CALLBACK ISOgetBuffer_compr(void) {
#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
char alt_bin_filename[MAXPATHLEN];
const char *bin_filename;
char image_str[1024];
- int is_chd = 0;
if (cdHandle != NULL) {
return 0; // it's already open
CDR_getBuffer = ISOgetBuffer;
cdimg_read_func = cdread_normal;
+ cdimg_read_sub_func = NULL;
if (parsetoc(GetIsoFile()) == 0) {
strcat(image_str, "[+toc]");
strcat(image_str, "[+chd]");
CDR_getBuffer = ISOgetBuffer_chd;
cdimg_read_func = cdread_chd;
- is_chd = 1;
+ cdimg_read_sub_func = cdread_sub_chd;
}
#endif
}
// guess whether it is mode1/2048
- if (ftello(cdHandle) % 2048 == 0) {
+ if (cdimg_read_func == cdread_normal && ftello(cdHandle) % 2048 == 0) {
unsigned int modeTest = 0;
fseek(cdHandle, 0, SEEK_SET);
if (!fread(&modeTest, sizeof(modeTest), 1, cdHandle)) {
-#ifndef NDEBUG
SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
-#endif
- return -1;
}
if (SWAP32(modeTest) != 0xffffff00) {
strcat(image_str, "[2048]");
PrintTracks();
- if (subChanMixed && !is_chd)
+ if (subChanMixed && cdimg_read_func == cdread_normal) {
cdimg_read_func = cdread_sub_mixed;
- else if (isMode1ISO)
+ cdimg_read_sub_func = cdread_sub_sub_mixed;
+ }
+ else if (isMode1ISO) {
cdimg_read_func = cdread_2048;
+ cdimg_read_sub_func = NULL;
+ }
// make sure we have another handle open for cdda
if (numtracks > 1 && ti[1].handle == NULL) {
return 0;
}
- if (pregapOffset) {
- subChanMissing = FALSE;
- if (sector >= pregapOffset) {
- sector -= 2 * 75;
- if (sector < pregapOffset)
- subChanMissing = TRUE;
- }
- }
+ if (pregapOffset && sector >= pregapOffset)
+ sector -= 2 * 75;
ret = cdimg_read_func(cdHandle, 0, cdbuffer, sector);
- if (ret < 0)
+ if (ret < 12*2 + 2048)
return 0;
- if (subHandle != NULL) {
- fseek(subHandle, sector * SUB_FRAMESIZE, SEEK_SET);
- if (fread(subbuffer, 1, SUB_FRAMESIZE, subHandle) != SUB_FRAMESIZE)
- /* Faulty subchannel data shouldn't cause a read failure */
- return 0;
-
- if (subChanRaw) DecodeRawSubData();
- }
-
return 1;
}
}
// gets subchannel data
-static unsigned char* CALLBACK ISOgetBufferSub(void) {
- if ((subHandle != NULL || subChanMixed) && !subChanMissing) {
- return subbuffer;
+static unsigned char* CALLBACK ISOgetBufferSub(int sector) {
+ if (pregapOffset && sector >= pregapOffset) {
+ sector -= 2 * 75;
+ if (sector < pregapOffset) // ?
+ return NULL;
+ }
+
+ if (cdimg_read_sub_func != NULL) {
+ if (cdimg_read_sub_func(cdHandle, sector) != SUB_FRAMESIZE)
+ return NULL;
+ }
+ else if (subHandle != NULL) {
+ if (fseek(subHandle, sector * SUB_FRAMESIZE, SEEK_SET))
+ return NULL;
+ if (fread(subbuffer, 1, SUB_FRAMESIZE, subHandle) != SUB_FRAMESIZE)
+ return NULL;
+ }
+ else {
+ return NULL;
}
- return NULL;
+ if (subChanRaw) DecodeRawSubData();
+ return subbuffer;
}
static long CALLBACK ISOgetStatus(struct CdrStat *stat) {