summaryrefslogtreecommitdiff
path: root/libpcsxcore
diff options
context:
space:
mode:
authorSND\shalma_cp <SND\shalma_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2010-09-28 14:07:40 +0000
committerSND\shalma_cp <SND\shalma_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2010-09-28 14:07:40 +0000
commitda14cf2c433e99eaa9ae14c7a1e589c20c93073b (patch)
tree0aa0c5022860b52c5b7b20d844e1dc970f79797a /libpcsxcore
parentf90c726e013a832cea1ce213e5251b9a013ad8a1 (diff)
downloadpcsxr-da14cf2c433e99eaa9ae14c7a1e589c20c93073b.tar.gz
Rayman, BIOS Music Player, GameShark Music Players
- cdriso.c: Forward + Backward (rewind) support, Data track wiping during audio play, GetStatus (time) fixes - cdrom.c: CdlForward, CdlBackward, CdlID (auto boot Music CDs with BIOS), CdlStop, CdlPause, CdlPlay (support BIOS play + pause / resume), CdlGetlocP (timing, output results), REPPLAY (report play times - Rayman, BIOS) now work - cdrom.h: Forward, Backward states; Larger result buffer NOTE: Must use iso images with subchannel data for Rayman and Music Players to work. And use latest PCSX-r PEOPS DSound plugin. git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@57823 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'libpcsxcore')
-rw-r--r--libpcsxcore/cdriso.c85
-rw-r--r--libpcsxcore/cdrom.c543
-rw-r--r--libpcsxcore/cdrom.h4
3 files changed, 438 insertions, 194 deletions
diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c
index fbdb9eb1..cb6527d7 100644
--- a/libpcsxcore/cdriso.c
+++ b/libpcsxcore/cdriso.c
@@ -66,8 +66,8 @@ extern void *hCDRDriver;
struct trackinfo {
enum {DATA, CDDA} type;
- char start[3]; // MSF-format
- char length[3]; // MSF-format
+ u8 start[3]; // MSF-format
+ u8 length[3]; // MSF-format
};
#define MAXTRACKS 100 /* How many tracks can a CD hold? */
@@ -161,8 +161,6 @@ static void *playthread(void *param)
t = GetTickCount() + CDDA_FRAMETIME;
- sec = cddaCurOffset / CD_FRAMESIZE_RAW;
-
if (subChanMixed) {
s = 0;
@@ -181,6 +179,8 @@ static void *playthread(void *param)
else {
s = fread(sndbuffer, 1, sizeof(sndbuffer), cddaHandle);
+ sec = cddaCurOffset / CD_FRAMESIZE_RAW;
+
if (subHandle != NULL) {
fseek(subHandle, sec * SUB_FRAMESIZE, SEEK_SET);
fread(subbuffer, 1, SUB_FRAMESIZE, subHandle);
@@ -204,10 +204,53 @@ static void *playthread(void *param)
}
}
+ // wipe data track
+ if( subHandle || subChanInterleaved ) {
+ if( ti[ ((struct SubQ *) subbuffer)->TrackNumber ].type == DATA )
+ memset( sndbuffer, 0, s );
+ }
+
SPU_playCDDAchannel((short *)sndbuffer, s);
}
cddaCurOffset += s;
+
+
+ // BIOS CD Player: Fast forward / reverse seek
+ if( cdr.FastForward ) {
+ // ~+0.25 sec
+ cddaCurOffset += CD_FRAMESIZE_RAW * 75/4;
+
+#if 0
+ // Bad idea: too much static
+ if( subChanInterleaved )
+ fseek( cddaHandle, s * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET );
+ else
+ fseek( cddaHandle, s * CD_FRAMESIZE_RAW, SEEK_SET );
+#endif
+ }
+ else if( cdr.FastBackward ) {
+ // ~-0.25 sec
+ cddaCurOffset -= CD_FRAMESIZE_RAW * 75/4;
+ if( cddaCurOffset & 0x80000000 ) {
+ cddaCurOffset = 0;
+ cdr.FastBackward = 0;
+
+ playing = 0;
+ fclose(cddaHandle);
+ cddaHandle = NULL;
+ initial_offset = 0;
+ break;
+ }
+
+#if 0
+ // Bad idea: too much static
+ if( subChanInterleaved )
+ fseek( cddaHandle, s * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET );
+ else
+ fseek( cddaHandle, s * CD_FRAMESIZE_RAW, SEEK_SET );
+#endif
+ }
}
#ifdef _WIN32
@@ -862,21 +905,25 @@ static unsigned char* CALLBACK ISOgetBufferSub(void) {
}
static long CALLBACK ISOgetStatus(struct CdrStat *stat) {
- int sec;
-
- CDR__getStatus(stat);
-
- if (playing) {
- stat->Type = 0x02;
- stat->Status |= 0x80;
- sec = cddaCurOffset / CD_FRAMESIZE_RAW;
- sec2msf(sec, (char *)stat->Time);
- }
- else {
- stat->Type = 0x01;
- }
-
- return 0;
+ u32 sect;
+
+ CDR__getStatus(stat);
+
+ if (playing) {
+ stat->Status |= 0x80;
+ }
+
+ // relative -> absolute time
+ sect = cddaCurOffset / CD_FRAMESIZE_RAW + 150;
+ sec2msf(sect, (u8 *)stat->Time);
+
+ if (subHandle != NULL || subChanInterleaved) {
+ stat->Type = ti[ ((struct SubQ *) subbuffer)->TrackNumber ].type;
+ }
+ else
+ stat->Type = ti[ cdr.CurTrack ].type;
+
+ return 0;
}
void cdrIsoInit(void) {
diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c
index a6e40834..2924461b 100644
--- a/libpcsxcore/cdrom.c
+++ b/libpcsxcore/cdrom.c
@@ -122,7 +122,9 @@ static struct SubQ *subq;
if (cdr.Play) { \
if (!Config.Cdda) CDR_stop(); \
cdr.StatP &= ~0x80; \
- cdr.Play = FALSE; \
+ cdr.Play = FALSE; \
+ cdr.FastForward = 0; \
+ cdr.FastBackward = 0; \
} \
}
@@ -132,6 +134,37 @@ static struct SubQ *subq;
cdr.ResultReady = 1; \
}
+void Find_CurTrack() {
+ cdr.CurTrack = 0;
+
+ if (CDR_getTN(cdr.ResultTN) != -1) {
+ int lcv;
+
+ for( lcv = 1; lcv < cdr.ResultTN[1]; lcv++ ) {
+ if (CDR_getTD((u8)(lcv), cdr.ResultTD) != -1) {
+ u32 sect1, sect2;
+
+#ifdef CDR_LOG___0
+ CDR_LOG( "curtrack %d %d %d | %d %d %d | %d\n",
+ cdr.SetSector[0], cdr.SetSector[1], cdr.SetSector[2],
+ cdr.ResultTD[0], cdr.ResultTD[1], cdr.ResultTD[2],
+ cdr.CurTrack );
+#endif
+
+ // find next track boundary
+ sect1 = cdr.SetSector[0] * 60 * 75 + cdr.SetSector[1] * 75 + cdr.SetSector[2];
+ sect2 = cdr.ResultTD[2] * 60 * 75 + cdr.ResultTD[1] * 75 + cdr.ResultTD[0];
+ if( sect1 >= sect2 ) {
+ cdr.CurTrack++;
+ continue;
+ }
+ }
+
+ break;
+ }
+ }
+}
+
static void ReadTrack() {
cdr.Prev[0] = itob(cdr.SetSector[0]);
cdr.Prev[1] = itob(cdr.SetSector[1]);
@@ -209,16 +242,30 @@ void cdrInterrupt() {
cdr.CmdProcess = 0;
SetResultSize(1);
cdr.StatP |= 0x2;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Complete;
+
+
+ // GameShark CD Player: Calls 2x + Play 2x
+ if( cdr.FastForward == 0 ) cdr.FastForward = 2;
+ else cdr.FastForward++;
+
+ cdr.FastBackward = 0;
break;
case CdlBackward:
cdr.CmdProcess = 0;
SetResultSize(1);
cdr.StatP |= 0x2;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Complete;
+
+
+ // GameShark CD Player: Calls 2x + Play 2x
+ if( cdr.FastBackward == 0 ) cdr.FastBackward = 2;
+ else cdr.FastBackward++;
+
+ cdr.FastForward = 0;
break;
case CdlStandby:
@@ -322,15 +369,22 @@ void cdrInterrupt() {
break;
case CdlGetlocP:
- SetResultSize(8);
+ SetResultSize(17);
+ memset( cdr.Result, 0, 17 );
+
subq = (struct SubQ *)CDR_getBufferSub();
- // DATA + AUDIO has subchannel data
if (subq != NULL) {
- cdr.Result[0] = subq->TrackNumber;
- cdr.Result[1] = subq->IndexNumber;
- memcpy(cdr.Result + 2, subq->TrackRelativeAddress, 3);
- memcpy(cdr.Result + 5, subq->AbsoluteAddress, 3);
+ // Subchannel block #1
+ cdr.Result[0] = subq->TrackNumber;
+ cdr.Result[1] = subq->IndexNumber;
+ memcpy(cdr.Result+2, subq->TrackRelativeAddress, 3);
+ memcpy(cdr.Result+5, subq->AbsoluteAddress, 3);
+
+
+ // GameShark CDX CD Player: Subchannel block #2
+ cdr.Result[16] = subq->TrackNumber;
+
// subQ integrity check
if (calcCrc((u8 *)subq + 12, 10) != (((u16)subq->CRC[0] << 8) | subq->CRC[1])) {
@@ -357,6 +411,55 @@ void cdrInterrupt() {
memcpy(cdr.Result + 5, cdr.Prev, 3);
}
+#if 1
+ // FIXME!!!
+ if( cdr.LidCheck ) {
+ memset( cdr.Result, 0, 17 );
+
+ // each state needs ~50 tries
+ if( cdr.LidCheck < 130 )
+ cdr.LidCheck++;
+ else
+ cdr.LidCheck = 0;
+
+ i = stat.Status;
+ if (CDR_getStatus(&stat) != -1) {
+ // Hack: Fake CDROM seek / spin time
+ static int seek_time = 0;
+
+ if (stat.Type == 0xff) {
+ }
+ else if (stat.Status & 0x10) {
+ // unknown #1 - status?
+ // unknown #2 - case open?
+
+ cdr.Result[0] = 0x11;
+ cdr.Result[1] = 0x80;
+ }
+ else if ( i & 0x10 ) {
+ cdr.Result[0] = 0x13;
+ cdr.Result[1] = 0x80;
+
+ // minimum tries for GS CDX 3.3
+ seek_time = 120;
+ }
+ else if ( seek_time > 60 ) {
+ cdr.Result[0] = 0x13;
+ cdr.Result[1] = 0x80;
+
+ seek_time--;
+ }
+ else if( seek_time ) {
+ // GameShark CDX swap
+ cdr.Result[0] = 0x01;
+ cdr.Result[1] = 0x00;
+
+ seek_time--;
+ }
+ }
+ }
+#endif
+
cdr.Stat = Acknowledge;
break;
@@ -457,21 +560,26 @@ void cdrInterrupt() {
break;
case CdlID + 0x20:
- SetResultSize(8);
- if (CDR_getStatus(&stat) == -1) {
- cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player
- cdr.Result[1] = 0x00; // 0x80 leads to the menu in the bios, else loads CD
- }
- else {
- if (stat.Type == 2) {
- cdr.Result[0] = 0x08;
- cdr.Result[1] = 0x10;
- }
- else {
- cdr.Result[0] = 0x00;
- cdr.Result[1] = 0x00;
- }
- }
+ SetResultSize(8);
+ if (CDR_getStatus(&stat) == -1) {
+ cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player
+ cdr.Result[1] = 0x00; // 0x80 leads to the menu in the bios, else loads CD
+ }
+ else {
+ if (stat.Type == 2) {
+ // Music CD
+ cdr.Result[0] = 0x08;
+ cdr.Result[1] = 0x10;
+
+ cdr.Result[1] |= 0x80;
+ }
+ else {
+ // Data CD
+ cdr.Result[0] = 0x08;
+ cdr.Result[1] = 0x00;
+ }
+ }
+
cdr.Result[1] |= 0x80;
cdr.Result[2] = 0x00;
cdr.Result[3] = 0x00;
@@ -539,26 +647,67 @@ void cdrInterrupt() {
break;
case REPPLAY:
- if ((cdr.Mode & 5) != 5) break;
- if (CDR_getStatus(&stat) == -1) {
- cdr.Result[0] = 0;
- cdr.Result[1] = 0;
- cdr.Result[2] = 0;
- cdr.Result[3] = 0;
- cdr.Result[4] = 0;
- cdr.Result[5] = 0;
- cdr.Result[6] = 0;
- cdr.Result[7] = 0;
- }
- else
- // FIXME!!
- //memcpy(cdr.Result, &stat.Track, 8);
- 0;
-
- cdr.Stat = 1;
- SetResultSize(8);
- AddIrqQueue(REPPLAY_ACK, cdReadTime);
- break;
+ if ((cdr.Mode & 5) != 5) break;
+
+ memset( cdr.Result, 0, 8 );
+ if( CDR_getStatus(&stat) != -1) {
+ // HACK: Switch between local / absolute times
+ static u8 report_time = 1;
+
+
+ subq = (struct SubQ *)CDR_getBufferSub();
+
+ if (subq != NULL ) {
+ /*
+ skip subQ integrity check (audio playback)
+ mainly useful for DATA LibCrypt checking
+ */
+ //if( SWAP16(subq->CRC) != calcCrc((unsigned char *)subq + 12, 10) )
+
+ cdr.Result[0] = cdr.StatP;
+
+
+ // Rayman: audio pregap flag / track change
+ // - not all CDs will use PREGAPs, so we track it manually
+ if( cdr.CurTrack < btoi( subq->TrackNumber ) ) {
+ cdr.Result[0] |= 0x10;
+
+ cdr.CurTrack = btoi( subq->TrackNumber );
+ }
+
+
+ // BIOS CD Player: data already BCD format
+ cdr.Result[1] = subq->TrackNumber;
+ cdr.Result[2] = subq->IndexNumber;
+
+
+ // BIOS CD Player: switch between local / absolute times
+ if( report_time == 0 ) {
+ cdr.Result[3] = subq->AbsoluteAddress[0];
+ cdr.Result[4] = subq->AbsoluteAddress[1];
+ cdr.Result[5] = subq->AbsoluteAddress[2];
+
+ report_time = 1;
+ }
+ else {
+ cdr.Result[3] = subq->TrackRelativeAddress[0];
+ cdr.Result[4] = subq->TrackRelativeAddress[1];
+ cdr.Result[5] = subq->TrackRelativeAddress[2];
+
+ cdr.Result[4] |= 0x80;
+
+ report_time = 0;
+ }
+ }
+ }
+
+ // Rayman: Logo freeze
+ cdr.ResultReady = 1;
+
+ cdr.Stat = 1;
+ SetResultSize(8);
+ AddIrqQueue(REPPLAY_ACK, cdReadTime);
+ break;
case 0xff:
return;
@@ -569,7 +718,8 @@ void cdrInterrupt() {
}
// check case open/close
- if (cdr.LidCheck > 0) {
+ if( cdr.LidCheck > 0 && Irq != CdlGetlocP ) {
+ // if (cdr.LidCheck > 0) {
cdr.LidCheck--;
i = stat.Status;
@@ -815,55 +965,119 @@ void cdrWrite1(unsigned char rt) {
break;
case CdlSetloc:
- StopReading();
- cdr.Seeked = FALSE;
- for (i = 0; i < 3; i++)
- cdr.SetSector[i] = btoi(cdr.Param[i]);
- cdr.SetSector[3] = 0;
-/* if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) {
- *(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek;
- }*/
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
+ StopReading();
+ cdr.Seeked = FALSE;
+ for (i = 0; i < 3; i++)
+ cdr.SetSector[i] = btoi(cdr.Param[i]);
+ cdr.SetSector[3] = 0;
+
+#ifdef DVD5_HACK
+ // PS1 DVD5 hack (shalma's disc combining kits)
+ dvd5_mode = cdr.Param[2] & 0x80;
+
+ if( CDR__setDVD5 ) {
+ if( cdr.Param[2] & 0x80 )
+ CDR__setDVD5(1);
+ else if( cdr.Param[1] & 0x80 )
+ CDR__setDVD5(2);
+ else
+ CDR__setDVD5(0);
+ }
+
+ cdr.Param[1] &= 0x7f;
+ cdr.Param[2] &= 0x7f;
+#endif
+
+ /*
+ if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) {
+ *(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek;
+ }*/
+
+ cdr.Ctrl |= 0x80;
+ cdr.Stat = NoIntr;
AddIrqQueue(cdr.Cmd, 0x1000);
- break;
+ break;
case CdlPlay:
- if (!cdr.SetSector[0] & !cdr.SetSector[1] & !cdr.SetSector[2]) {
- if (CDR_getTN(cdr.ResultTN) != -1) {
- if (cdr.CurTrack > cdr.ResultTN[1])
- cdr.CurTrack = cdr.ResultTN[1];
- if (CDR_getTD((unsigned char)(cdr.CurTrack), cdr.ResultTD) != -1) {
- int tmp = cdr.ResultTD[2];
- cdr.ResultTD[2] = cdr.ResultTD[0];
- cdr.ResultTD[0] = tmp;
- if (!Config.Cdda) CDR_play(cdr.ResultTD);
- }
- }
- } else if (!Config.Cdda) {
- CDR_play(cdr.SetSector);
- }
- cdr.Play = TRUE;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x1000);
- break;
+ // Rayman: detect track changes
+ Find_CurTrack();
+
+
+ // GameShark CD Player: Calls 2x + Play 2x
+ if( cdr.FastBackward || cdr.FastForward ) {
+ if( cdr.FastForward ) cdr.FastForward--;
+ if( cdr.FastBackward ) cdr.FastBackward--;
+
+ if( cdr.FastBackward == 0 && cdr.FastForward == 0 ) {
+ if( CDR_getStatus(&stat) != -1 ) {
+ cdr.SetSector[0] = stat.Time[0];
+ cdr.SetSector[1] = stat.Time[1];
+ cdr.SetSector[2] = stat.Time[2];
+ }
+ }
+ }
+
+
+ if (!Config.Cdda) {
+ // BIOS CD Player
+ // - Pause player, hit Track 01/02/../xx (Setloc issued!!)
+
+ // GameShark CD Player: Resume play
+ if( cdr.ParamC == 0 ) {
+ CDR_play( cdr.SetSector );
+ }
+ else
+ {
+ // BIOS CD Player: Resume play
+ if( cdr.Param[0] == 0 ) {
+ CDR_play( cdr.SetSector );
+ }
+
+ else {
+ // BIOS CD Player: Allow track replaying
+ StopCdda();
+
+
+ cdr.CurTrack = btoi( cdr.Param[0] );
+
+ if (CDR_getTN(cdr.ResultTN) != -1) {
+ // check last track
+ if (cdr.CurTrack > cdr.ResultTN[1])
+ cdr.CurTrack = cdr.ResultTN[1];
+
+ if (CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD) != -1) {
+ cdr.SetSector[0] = cdr.ResultTD[2];
+ cdr.SetSector[1] = cdr.ResultTD[1];
+ cdr.SetSector[2] = cdr.ResultTD[0];
+
+ CDR_play(cdr.SetSector);
+ }
+ }
+ }
+ }
+ }
+
+ cdr.Play = TRUE;
+ cdr.Ctrl |= 0x80;
+ cdr.Stat = NoIntr;
+ AddIrqQueue(cdr.Cmd, 0x1000);
+ break;
case CdlForward:
- if (cdr.CurTrack < 0xaa)
- cdr.CurTrack++;
- cdr.Ctrl |= 0x80;
+ //if (cdr.CurTrack < 0xaa)
+ // cdr.CurTrack++;
+ cdr.Ctrl |= 0x80;
cdr.Stat = NoIntr;
AddIrqQueue(cdr.Cmd, 0x1000);
- break;
+ break;
case CdlBackward:
- if (cdr.CurTrack > 1)
- cdr.CurTrack--;
- cdr.Ctrl |= 0x80;
+ //if (cdr.CurTrack > 1)
+ //cdr.CurTrack--;
+ cdr.Ctrl |= 0x80;
cdr.Stat = NoIntr;
AddIrqQueue(cdr.Cmd, 0x1000);
- break;
+ break;
case CdlReadN:
cdr.Irq = 0;
@@ -882,20 +1096,45 @@ void cdrWrite1(unsigned char rt) {
break;
case CdlStop:
- StopCdda();
- StopReading();
- cdr.Ctrl |= 0x80;
+ // GameShark CD Player: Reset CDDA to track start
+ if( CDR_getStatus(&stat) != -1 ) {
+ cdr.SetSector[0] = stat.Time[0];
+ cdr.SetSector[1] = stat.Time[1];
+ cdr.SetSector[2] = stat.Time[2];
+
+ Find_CurTrack();
+
+
+ // grab time for current track
+ CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD);
+
+ cdr.SetSector[0] = cdr.ResultTD[2];
+ cdr.SetSector[1] = cdr.ResultTD[1];
+ cdr.SetSector[2] = cdr.ResultTD[0];
+ }
+
+ StopCdda();
+ StopReading();
+
+ cdr.Ctrl |= 0x80;
cdr.Stat = NoIntr;
AddIrqQueue(cdr.Cmd, 0x1000);
- break;
+ break;
case CdlPause:
- StopCdda();
- StopReading();
- cdr.Ctrl |= 0x80;
+ // GameShark CD Player: save time for resume
+ if( CDR_getStatus(&stat) != -1 ) {
+ cdr.SetSector[0] = stat.Time[0];
+ cdr.SetSector[1] = stat.Time[1];
+ cdr.SetSector[2] = stat.Time[2];
+ }
+
+ StopCdda();
+ StopReading();
+ cdr.Ctrl |= 0x80;
cdr.Stat = NoIntr;
AddIrqQueue(cdr.Cmd, 0x80000);
- break;
+ break;
case CdlReset:
case CdlInit:
@@ -951,16 +1190,23 @@ void cdrWrite1(unsigned char rt) {
break;
case CdlGetlocP:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x1000);
- break;
+ cdr.Ctrl |= 0x80;
+ cdr.Stat = NoIntr;
+ AddIrqQueue(cdr.Cmd, 0x1000);
+
+ // GameShark CDX / Lite Player: pretty narrow time window
+ // - doesn't always work due to time inprecision
+ //AddIrqQueue(cdr.Cmd, 0x28);
+ break;
case CdlGetTN:
- cdr.Ctrl |= 0x80;
+ cdr.Ctrl |= 0x80;
cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x1000);
- break;
+ //AddIrqQueue(cdr.Cmd, 0x1000);
+
+ // GameShark CDX CD Player: very long time
+ AddIrqQueue(cdr.Cmd, 0x100000);
+ break;
case CdlGetTD:
cdr.Ctrl |= 0x80;
@@ -1075,21 +1321,39 @@ unsigned char cdrRead3(void) {
void cdrWrite3(unsigned char rt) {
#ifdef CDR_LOG
CDR_LOG("cdrWrite3() Log: CD3 write: %x\n", rt);
-#endif
- if (rt == 0x07 && cdr.Ctrl & 0x1) {
+#endif
+
+ // GameShark CDX CD Player: Irq timing mania
+ if( rt == 0 &&
+ cdr.Irq != 0 && cdr.Irq != 0xff &&
+ cdr.ResultReady == 0 ) {
+
+ // GS CDX: ~0x28 cycle timing - way too precise
+ if( cdr.Irq == CdlGetlocP ) {
+ cdrInterrupt();
+
+ psxRegs.interrupt &= ~(1 << PSXINT_CDR);
+ }
+ }
+
+
+ if (rt == 0x07 && cdr.Ctrl & 0x1) {
cdr.Stat = 0;
if (cdr.Irq == 0xff) {
cdr.Irq = 0;
return;
- }
+ }
+
if (cdr.Irq)
- CDR_INT(cdr.eCycle);
+ CDR_INT(cdr.eCycle);
+
if (cdr.Reading && !cdr.ResultReady)
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
return;
- }
+ }
+
if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) {
cdr.Readed = 1;
cdr.pTransfer = cdr.Transfer;
@@ -1103,75 +1367,6 @@ void cdrWrite3(unsigned char rt) {
break;
}
}
-
- /*
- GameShark CDX 3.3
-
- TODO: Can we relax the rules?
- */
- if (rt == 0 && cdr.Ctrl == 0xd8 && cdr.Readed == 1) {
- u32 i;
-
-
- // low-level status access
- SetResultSize(15);
-
-
- i = stat.Status;
- if (CDR_getStatus(&stat) != -1) {
- // Hack: Fake CDROM seek / spin time
- static int seek_time = 0;
-
- if (stat.Type == 0xff) {
- }
- else if (stat.Status & 0x10) {
- // unknown #1 - status?
- // unknown #2 - case open?
-
- cdr.Result[0] = 0x11;
- cdr.Result[1] = 0x80;
- }
- else if ( i & 0x10 ) {
- cdr.Result[0] = 0x13;
- cdr.Result[1] = 0x80;
-
- // minimum 50 tries for GS CDX 3.3
- seek_time = 50;
- }
- else if ( seek_time ) {
- cdr.Result[0] = 0x13;
- cdr.Result[1] = 0x80;
-
- seek_time--;
- }
- else
- {
- cdr.Result[0] = 0x01;
- cdr.Result[1] = 0x00;
- }
-
- // unknown #3
- cdr.Result[2] = 0;
-
- // unknown #4 - error?
- cdr.Result[3] = 0;
-
- // unknown #5-14
- cdr.Result[4] = 0;
- cdr.Result[5] = 0;
- cdr.Result[6] = 0;
- cdr.Result[7] = 0;
- cdr.Result[8] = 0;
- cdr.Result[9] = 0;
- cdr.Result[10] = 0;
- cdr.Result[11] = 0;
- cdr.Result[12] = 0;
- cdr.Result[13] = 0;
-
- // unknown #15 - error?
- cdr.Result[14] = 0;
- }
- }
}
void psxDma3(u32 madr, u32 bcr, u32 chcr) {
diff --git a/libpcsxcore/cdrom.h b/libpcsxcore/cdrom.h
index 9e4c6fa7..da4fe108 100644
--- a/libpcsxcore/cdrom.h
+++ b/libpcsxcore/cdrom.h
@@ -56,7 +56,7 @@ typedef struct {
unsigned char Prev[4];
unsigned char Param[8];
- unsigned char Result[15];
+ unsigned char Result[16];
unsigned char ParamC;
unsigned char ParamP;
@@ -89,6 +89,8 @@ typedef struct {
boolean Seeked;
u8 LidCheck;
+ u8 FastForward;
+ u8 FastBackward;
} cdrStruct;
extern cdrStruct cdr;