#include <process.h>
#include <windows.h>
#define strcasecmp _stricmp
-#define usleep(x) (Sleep((x) / 1000))
#else
#include <pthread.h>
#include <sys/time.h>
static unsigned char cdbuffer[CD_FRAMESIZE_RAW];
static unsigned char subbuffer[SUB_FRAMESIZE];
-static unsigned char sndbuffer[CD_FRAMESIZE_RAW * 10];
-
-#define CDDA_FRAMETIME (1000 * (sizeof(sndbuffer) / CD_FRAMESIZE_RAW) / 75)
-
-#ifdef _WIN32
-static HANDLE threadid;
-#else
-static pthread_t threadid;
-#endif
-static unsigned int initial_offset = 0;
static boolean playing = FALSE;
static boolean cddaBigEndian = FALSE;
// cdda sectors in toc, byte offset in file
static unsigned int cdda_cur_sector;
-static unsigned int cdda_first_sector;
static unsigned int cdda_file_offset;
/* Frame offset into CD image where pregap data would be found if it was there.
* If a game seeks there we must *not* return subchannel data since it's
}
}
-#ifndef _WIN32
-static long GetTickCount(void) {
- static time_t initial_time = 0;
- struct timeval now;
-
- gettimeofday(&now, NULL);
-
- if (initial_time == 0) {
- initial_time = now.tv_sec;
- }
-
- return (now.tv_sec - initial_time) * 1000L + now.tv_usec / 1000L;
-}
-#endif
-
-// this thread plays audio data
-#ifdef _WIN32
-static void playthread(void *param)
-#else
-static void *playthread(void *param)
-#endif
-{
- long osleep, d, t, i, s;
- unsigned char tmp;
- int ret = 0, sector_offs;
-
- t = GetTickCount();
-
- while (playing) {
- s = 0;
- for (i = 0; i < sizeof(sndbuffer) / CD_FRAMESIZE_RAW; i++) {
- sector_offs = cdda_cur_sector - cdda_first_sector;
- if (sector_offs < 0) {
- d = CD_FRAMESIZE_RAW;
- memset(sndbuffer + s, 0, d);
- }
- else {
- d = cdimg_read_func(cddaHandle, cdda_file_offset,
- sndbuffer + s, sector_offs);
- if (d < CD_FRAMESIZE_RAW)
- break;
- }
-
- s += d;
- cdda_cur_sector++;
- }
-
- if (s == 0) {
- playing = FALSE;
- initial_offset = 0;
- break;
- }
-
- if (!cdr.Muted && playing) {
- if (cddaBigEndian) {
- for (i = 0; i < s / 2; i++) {
- tmp = sndbuffer[i * 2];
- sndbuffer[i * 2] = sndbuffer[i * 2 + 1];
- sndbuffer[i * 2 + 1] = tmp;
- }
- }
-
- // can't do it yet due to readahead..
- //cdrAttenuate((short *)sndbuffer, s / 4, 1);
- do {
- ret = SPU_playCDDAchannel((short *)sndbuffer, s);
- if (ret == 0x7761)
- {
- usleep(6 * 1000);
- }
- } while (ret == 0x7761 && playing); // rearmed_wait
- }
-
- if (ret != 0x676f) { // !rearmed_go
- // do approx sleep
- long now;
-
- // HACK: stop feeding data while emu is paused
- extern int stop;
- while (stop && playing)
- {
- usleep(10000);
- }
-
- now = GetTickCount();
- osleep = t - now;
- if (osleep <= 0) {
- osleep = 1;
- t = now;
- }
- else if (osleep > CDDA_FRAMETIME) {
- osleep = CDDA_FRAMETIME;
- t = now;
- }
-
- usleep(osleep * 1000);
- t += CDDA_FRAMETIME;
- }
-
- }
-
-#ifdef _WIN32
- _endthread();
-#else
- pthread_exit(0);
- return NULL;
-#endif
-}
-
-// stop the CDDA playback
-static void stopCDDA() {
- if (!playing) {
- return;
- }
-
- playing = FALSE;
-#ifdef _WIN32
- WaitForSingleObject(threadid, INFINITE);
-#else
- pthread_join(threadid, NULL);
-#endif
-}
-
-// start the CDDA playback
-static void startCDDA(void) {
- if (playing) {
- stopCDDA();
- }
-
- playing = TRUE;
-
-#ifdef _WIN32
- threadid = (HANDLE)_beginthread(playthread, 0, NULL);
-#else
- pthread_create(&threadid, NULL, playthread, NULL);
-#endif
-}
-
// this function tries to get the .toc file of the given .bin
// the necessary data is put into the ti (trackinformation)-array
static int parsetoc(const char *isofile) {
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 = 150;
+ int file_offset = 0;
+
chd_img = calloc(1, sizeof(*chd_img));
if (chd_img == NULL)
goto fail_io;
cddaBigEndian = TRUE;
numtracks = 0;
- int frame_offset = 0;
- int file_offset = 0;
memset(ti, 0, sizeof(ti));
while (1)
else
break;
- if(md.track == 1)
- md.pregap = 150;
- else
- sec2msf(msf2sec(ti[md.track-1].length) + md.pregap, ti[md.track-1].length);
+ SysPrintf("chd: %s\n", meta);
+
+ if (md.track == 1) {
+ if (!strncmp(md.subtype, "RW", 2)) {
+ subChanMixed = TRUE;
+ if (!strcmp(md.subtype, "RW_RAW"))
+ subChanRaw = TRUE;
+ }
+ }
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++;
}
if (dest != cdbuffer) // copy avoid HACK
memcpy(dest, chd_img->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;
}
#endif
boolean isMode1ISO = FALSE;
char alt_bin_filename[MAXPATHLEN];
const char *bin_filename;
- char image_str[1024] = {0};
+ char image_str[1024];
+ int is_chd = 0;
if (cdHandle != NULL) {
return 0; // it's already open
return -1;
}
- sprintf(image_str, "Loaded CD Image: %s", GetIsoFile());
+ snprintf(image_str, sizeof(image_str) - 6*4 - 1,
+ "Loaded CD Image: %s", GetIsoFile());
cddaBigEndian = FALSE;
subChanMixed = FALSE;
strcat(image_str, "[+chd]");
CDR_getBuffer = ISOgetBuffer_chd;
cdimg_read_func = cdread_chd;
+ is_chd = 1;
}
#endif
PrintTracks();
- if (subChanMixed)
+ if (subChanMixed && !is_chd)
cdimg_read_func = cdread_sub_mixed;
else if (isMode1ISO)
cdimg_read_func = cdread_2048;
fclose(subHandle);
subHandle = NULL;
}
- stopCDDA();
+ playing = FALSE;
cddaHandle = NULL;
if (compr_img != NULL) {
// sector: byte 0 - minute; byte 1 - second; byte 2 - frame
// does NOT uses bcd format
static long CALLBACK ISOplay(unsigned char *time) {
- unsigned int i;
-
- if (numtracks <= 1)
- return 0;
-
- // find the track
- cdda_cur_sector = msf2sec((char *)time);
- for (i = numtracks; i > 1; i--) {
- cdda_first_sector = msf2sec(ti[i].start);
- if (cdda_first_sector <= cdda_cur_sector + 2 * 75)
- break;
- }
- cdda_file_offset = ti[i].start_offset;
-
- // find the file that contains this track
- for (; i > 1; i--)
- if (ti[i].handle != NULL)
- break;
-
- cddaHandle = ti[i].handle;
-
- if (SPU_playCDDAchannel != NULL)
- startCDDA();
-
+ playing = TRUE;
return 0;
}
// stops cdda audio
static long CALLBACK ISOstop(void) {
- stopCDDA();
+ playing = FALSE;
return 0;
}