summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSND\notaz_cp <SND\notaz_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2013-01-09 00:54:51 +0000
committerSND\notaz_cp <SND\notaz_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2013-01-09 00:54:51 +0000
commit1a252f87fff3d084bd3e936d5e3b68abbc19cfdd (patch)
tree20934dd8c3f5a17b02fb4946d19b66bed1291c59
parent05e0c2b22ce4340c990446557ab720740af0edf7 (diff)
downloadpcsxr-1a252f87fff3d084bd3e936d5e3b68abbc19cfdd.tar.gz
cdrom: merge code from PCSX ReARMed
- lots of hacks cleaned up - removes port3 reschedule (fixes FMVs with Brave Fencer Musashi, etc still working) - based on new information from Mednafen, nocash, and a few tests of my own git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@82129 e17a0e51-4ae3-4d35-97c3-1a29b211df97
-rwxr-xr-xlibpcsxcore/cdrom.c1964
-rwxr-xr-xlibpcsxcore/cdrom.h24
2 files changed, 647 insertions, 1341 deletions
diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c
index c7410777..cb271cc1 100755
--- a/libpcsxcore/cdrom.c
+++ b/libpcsxcore/cdrom.c
@@ -25,6 +25,24 @@
#include "ppf.h"
#include "psxdma.h"
+/* logging */
+#if 0
+#define CDR_LOG SysPrintf
+#else
+#define CDR_LOG(...)
+#endif
+#if 0
+#define CDR_LOG_I SysPrintf
+#else
+#define CDR_LOG_I(...)
+#endif
+#if 0
+#define CDR_LOG_IO SysPrintf
+#else
+#define CDR_LOG_IO(...)
+#endif
+//#define CDR_LOG_CMD_IRQ
+
cdrStruct cdr;
/* CD-ROM magic numbers */
@@ -59,14 +77,6 @@ cdrStruct cdr;
#define CdlReset 28
#define CdlReadToc 30
-#define AUTOPAUSE 249
-#define READ_ACK 250
-#define READ 251
-#define REPPLAY_ACK 252
-#define REPPLAY 253
-#define ASYNC 254
-/* don't set 255, it's reserved */
-
char *CmdName[0x100]= {
"CdlSync", "CdlNop", "CdlSetloc", "CdlPlay",
"CdlForward", "CdlBackward", "CdlReadN", "CdlStandby",
@@ -113,20 +123,27 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 };
#define STATUS_ROTATING (1<<1) // 0x02
#define STATUS_ERROR (1<<0) // 0x01
-#define XA_ATTENUATE 0
-#define CDDA_ATTENUATE 1
// 1x = 75 sectors per second
// PSXCLK = 1 sec in the ps
// so (PSXCLK / 75) = cdr read time (linuzappz)
#define cdReadTime (PSXCLK / 75)
+// for cdr.Seeked
+enum seeked_state {
+ SEEK_PENDING = 0,
+ SEEK_DONE = 1,
+};
+
static struct CdrStat stat;
-static struct SubQ *subq;
+extern unsigned int msf2sec(const char *msf);
+extern void sec2msf(unsigned int s, const char *msf);
-extern unsigned int msf2sec(char *msf);
-extern void sec2msf(unsigned int s, char *msf);
+// for that weird psemu API..
+static unsigned int fsm2sec(const u8 *msf) {
+ return ((msf[2] * 60 + msf[1]) * 75) + msf[0];
+}
extern long CALLBACK ISOinit(void);
@@ -154,43 +171,41 @@ extern SPUregisterCallback SPU_registerCallback;
#define H_CDRight 0x1f801db2
+// cdrInterrupt
#define CDR_INT(eCycle) { \
psxRegs.interrupt |= (1 << PSXINT_CDR); \
psxRegs.intCycle[PSXINT_CDR].cycle = eCycle; \
psxRegs.intCycle[PSXINT_CDR].sCycle = psxRegs.cycle; \
}
+// cdrReadInterrupt
#define CDREAD_INT(eCycle) { \
psxRegs.interrupt |= (1 << PSXINT_CDREAD); \
psxRegs.intCycle[PSXINT_CDREAD].cycle = eCycle; \
psxRegs.intCycle[PSXINT_CDREAD].sCycle = psxRegs.cycle; \
}
+// cdrDecodedBufferInterrupt
#define CDRDBUF_INT(eCycle) { \
psxRegs.interrupt |= (1 << PSXINT_CDRDBUF); \
psxRegs.intCycle[PSXINT_CDRDBUF].cycle = eCycle; \
psxRegs.intCycle[PSXINT_CDRDBUF].sCycle = psxRegs.cycle; \
}
+// cdrLidSeekInterrupt
#define CDRLID_INT(eCycle) { \
psxRegs.interrupt |= (1 << PSXINT_CDRLID); \
psxRegs.intCycle[PSXINT_CDRLID].cycle = eCycle; \
psxRegs.intCycle[PSXINT_CDRLID].sCycle = psxRegs.cycle; \
}
-#define CDRPLAY_INT(eCycle) { \
+// cdrPlayInterrupt
+#define CDRMISC_INT(eCycle) { \
psxRegs.interrupt |= (1 << PSXINT_CDRPLAY); \
psxRegs.intCycle[PSXINT_CDRPLAY].cycle = eCycle; \
psxRegs.intCycle[PSXINT_CDRPLAY].sCycle = psxRegs.cycle; \
}
-#define StartReading(type, eCycle) { \
- cdr.Reading = type; \
- cdr.FirstSector = 1; \
- cdr.Readed = 0xff; \
- AddIrqQueue(READ_ACK, eCycle); \
-}
-
#define StopReading() { \
if (cdr.Reading) { \
cdr.Reading = 0; \
@@ -211,31 +226,30 @@ extern SPUregisterCallback SPU_registerCallback;
}
#define SetResultSize(size) { \
- cdr.ResultP = 0; \
+ cdr.ResultP = 0; \
cdr.ResultC = size; \
cdr.ResultReady = 1; \
}
-void adjustTransferIndex()
+static void setIrq(void)
+{
+ if (cdr.Stat & cdr.Reg2)
+ psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+}
+
+static void adjustTransferIndex(void)
{
unsigned int bufSize = 0;
switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
- //Do we need a default case in this switch?
case MODE_SIZE_2340: bufSize = 2340; break;
case MODE_SIZE_2328: bufSize = 12 + 2328; break;
+ default:
case MODE_SIZE_2048: bufSize = 12 + 2048; break;
}
if (cdr.transferIndex >= bufSize)
- {
- if (bufSize == 0) {
- //Make sure we don't divide by zero
- //Do nothing
- } else {
- cdr.transferIndex %= bufSize;
- }
- }
+ cdr.transferIndex -= bufSize;
}
// FIXME: do this in SPU instead
@@ -282,7 +296,6 @@ void cdrDecodedBufferInterrupt()
CDRDBUF_INT( PSXCLK / 44100 * 0x100 );
}
-
void cdrLidSeekInterrupt()
{
// turn back on checking
@@ -339,15 +352,12 @@ void cdrLidSeekInterrupt()
}
}
-
-void Check_Shell( int Irq )
+static void Check_Shell( int Irq )
{
// check case open/close
if (cdr.LidCheck > 0)
{
-#ifdef CDR_LOG
CDR_LOG( "LidCheck\n" );
-#endif
// $20 = check lid state
if( cdr.LidCheck == 0x20 )
@@ -403,8 +413,7 @@ void Check_Shell( int Irq )
if( cdr.Stat == NoIntr )
cdr.Stat = Acknowledge;
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
-
+ setIrq();
// begin close-seek-ready cycle
CDRLID_INT( cdReadTime * 3 );
@@ -444,502 +453,220 @@ void Check_Shell( int Irq )
if( cdr.Stat == NoIntr )
cdr.Stat = Acknowledge;
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
- }
- }
-}
-
-
-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.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2],
- cdr.ResultTD[2], cdr.ResultTD[1], cdr.ResultTD[0],
- cdr.CurTrack );
-#endif
-
- // find next track boundary - only need m:s accuracy
- sect1 = cdr.SetSectorPlay[0] * 60 * 75 + cdr.SetSectorPlay[1] * 75;
- sect2 = cdr.ResultTD[2] * 60 * 75 + cdr.ResultTD[1] * 75;
-
- // Twisted Metal 4 - psx cdda pregap (2-sec)
- // - fix in-game music
- sect2 -= 75 * 2;
-
- if( sect1 >= sect2 ) {
- cdr.CurTrack++;
- continue;
- }
- }
-
- break;
+ setIrq();
}
}
}
-static void ReadTrack( u8 *time ) {
- cdr.Prev[0] = itob( time[0] );
- cdr.Prev[1] = itob( time[1] );
- cdr.Prev[2] = itob( time[2] );
-
-#ifdef CDR_LOG
- CDR_LOG("ReadTrack() Log: KEY *** %x:%x:%x\n", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]);
-#endif
- cdr.RErr = CDR_readTrack(cdr.Prev);
-}
-
-
-static void CDXA_Attenuation( s16 *buf, int size, int stereo, int attenuate_type )
+static void Find_CurTrack(const u8 *time)
{
- s16 *spsound;
- s32 lc = 0, rc = 0;
- int i;
-
- spsound = buf;
-
-#if 0
- // mono xa attenuation
- // - Tales of Phantasia (voice meter)
- if( stereo == 0 ) {
- s16 temp[32768];
- int dst;
-
- dst = 0;
- for( i = 0; i < size; i++, dst+=2 ) {
- temp[dst+0] = spsound[i];
- temp[dst+1] = spsound[i];
- }
+ int current, sect;
- size *= 2*2;
- memcpy( spsound, temp, size );
- }
-#endif
-
- for( i = 0; i < size / 2; i += 2 )
- {
- // Chronicles of the Sword - cutscene (xa), speech (cdda)
- if( attenuate_type == XA_ATTENUATE ) {
- lc = (spsound[i+0] * cdr.AttenuatorLeft[0] + spsound[i+1] * cdr.AttenuatorLeft[1]) / 128;
- rc = (spsound[i+1] * cdr.AttenuatorRight[0] + spsound[i+0] * cdr.AttenuatorRight[1]) / 128;
- } else if( attenuate_type == CDDA_ATTENUATE ) {
- lc = (spsound[i+0] * cdr.AttenuatorLeft[0] + spsound[i+1] * cdr.AttenuatorRight[1]) / 128;
- rc = (spsound[i+1] * cdr.AttenuatorRight[0] + spsound[i+0] * cdr.AttenuatorLeft[1]) / 128;
- }
+ current = msf2sec(time);
- if( lc < -32768 ) lc = -32768;
- if( rc < -32768 ) rc = -32768;
- if( lc > 32767 ) lc = 32767;
- if( rc > 32767 ) rc = 32767;
-
- spsound[i + 0] = lc;
- spsound[i + 1] = rc;
- }
-}
-
-
-void AddIrqQueue(unsigned char irq, unsigned long ecycle) {
- cdr.Irq = irq;
- cdr.eCycle = ecycle;
-
- // Doom: Force rescheduling
- // - Fixes boot
- CDR_INT(ecycle);
-}
-
-
-void Set_Track()
-{
- if (CDR_getTN(cdr.ResultTN) != -1) {
- int lcv;
-
- for( lcv = 1; lcv < cdr.ResultTN[1]; lcv++ ) {
- if (CDR_getTD((u8)(lcv), cdr.ResultTD) != -1) {
-#ifdef CDR_LOG___0
- CDR_LOG( "settrack %d %d %d | %d %d %d | %d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2],
- cdr.ResultTD[2], cdr.ResultTD[1], cdr.ResultTD[0],
- cdr.CurTrack );
-#endif
-
- // check if time matches track start (only need min, sec accuracy)
- // - m:s:f vs f:s:m
- if( cdr.SetSectorPlay[0] == cdr.ResultTD[2] &&
- cdr.SetSectorPlay[1] == cdr.ResultTD[1] ) {
- // skip pregap frames
- if( cdr.SetSectorPlay[2] < cdr.ResultTD[0] )
- cdr.SetSectorPlay[2] = cdr.ResultTD[0];
-
- break;
- }
- else if( cdr.SetSectorPlay[0] < cdr.ResultTD[2] )
- break;
- }
- }
+ for (cdr.CurTrack = 1; cdr.CurTrack < cdr.ResultTN[1]; cdr.CurTrack++) {
+ CDR_getTD(cdr.CurTrack + 1, cdr.ResultTD);
+ sect = fsm2sec(cdr.ResultTD);
+ if (sect - current >= 150)
+ break;
}
}
-
-static u8 fake_subq_local[3], fake_subq_real[3], fake_subq_index, fake_subq_change;
-void Create_Fake_Subq()
+static void generate_subq(const u8 *time)
{
- u8 temp_cur[3], temp_next[3], temp_start[3], pregap;
- int diff;
+ unsigned char start[3], next[3];
+ unsigned int this_s, start_s, next_s, pregap;
+ int relative_s;
- if (CDR_getTN(cdr.ResultTN) == -1) return;
- if( cdr.CurTrack+1 <= cdr.ResultTN[1] ) {
+ CDR_getTD(cdr.CurTrack, start);
+ if (cdr.CurTrack + 1 <= cdr.ResultTN[1]) {
pregap = 150;
- if( CDR_getTD(cdr.CurTrack+1, cdr.ResultTD) == -1 ) return;
- } else {
+ CDR_getTD(cdr.CurTrack + 1, next);
+ }
+ else {
// last track - cd size
pregap = 0;
- if( CDR_getTD(0, cdr.ResultTD) == -1 ) return;
- }
-
- if( cdr.Play == TRUE ) {
- temp_cur[0] = cdr.SetSectorPlay[0];
- temp_cur[1] = cdr.SetSectorPlay[1];
- temp_cur[2] = cdr.SetSectorPlay[2];
- } else {
- temp_cur[0] = btoi( cdr.Prev[0] );
- temp_cur[1] = btoi( cdr.Prev[1] );
- temp_cur[2] = btoi( cdr.Prev[2] );
+ next[0] = cdr.SetSectorEnd[2];
+ next[1] = cdr.SetSectorEnd[1];
+ next[2] = cdr.SetSectorEnd[0];
}
- fake_subq_real[0] = temp_cur[0];
- fake_subq_real[1] = temp_cur[1];
- fake_subq_real[2] = temp_cur[2];
+ this_s = msf2sec(time);
+ start_s = fsm2sec(start);
+ next_s = fsm2sec(next);
- temp_next[0] = cdr.ResultTD[2];
- temp_next[1] = cdr.ResultTD[1];
- temp_next[2] = cdr.ResultTD[0];
-
-
- // flag- next track
- if( msf2sec(temp_cur) >= msf2sec( temp_next )-pregap ) {
- fake_subq_change = 1;
+ cdr.TrackChanged = FALSE;
+ if (next_s - this_s < pregap) {
+ cdr.TrackChanged = TRUE;
cdr.CurTrack++;
-
- // end cd
- if( pregap == 0 ) StopCdda();
+ start_s = next_s;
}
- //////////////////////////////////////////////////
- //////////////////////////////////////////////////
+ cdr.subq.Index = 1;
- // repair
- if( cdr.CurTrack <= cdr.ResultTN[1] ) {
- if( CDR_getTD(cdr.CurTrack, cdr.ResultTD) == -1 ) return;
- } else {
- // last track - cd size
- if( CDR_getTD(0, cdr.ResultTD) == -1 ) return;
- }
-
- temp_start[0] = cdr.ResultTD[2];
- temp_start[1] = cdr.ResultTD[1];
- temp_start[2] = cdr.ResultTD[0];
-
-
-#ifdef CDR_LOG
- CDR_LOG( "CDDA FAKE SUB - %d:%d:%d / %d:%d:%d / %d:%d:%d\n",
- temp_cur[0], temp_cur[1], temp_cur[2],
- temp_start[0], temp_start[1], temp_start[2],
- temp_next[0], temp_next[1], temp_next[2]);
-#endif
-
-
-
- // local time - pregap / real
- diff = msf2sec(temp_cur) - msf2sec( temp_start );
- if( diff < 0 ) {
- fake_subq_index = 0;
-
- sec2msf( -diff, fake_subq_local );
- } else {
- fake_subq_index = 1;
-
- sec2msf( diff, fake_subq_local );
+ relative_s = this_s - start_s;
+ if (relative_s < 0) {
+ cdr.subq.Index = 0;
+ relative_s = -relative_s;
}
+ sec2msf(relative_s, cdr.subq.Relative);
+
+ cdr.subq.Track = itob(cdr.CurTrack);
+ cdr.subq.Relative[0] = itob(cdr.subq.Relative[0]);
+ cdr.subq.Relative[1] = itob(cdr.subq.Relative[1]);
+ cdr.subq.Relative[2] = itob(cdr.subq.Relative[2]);
+ cdr.subq.Absolute[0] = itob(time[0]);
+ cdr.subq.Absolute[1] = itob(time[1]);
+ cdr.subq.Absolute[2] = itob(time[2]);
}
+static void ReadTrack(const u8 *time) {
+ unsigned char tmp[3];
+ struct SubQ *subq;
+ u16 crc;
-void cdrPlayInterrupt_Autopause()
-{
- if ((cdr.Mode & (MODE_AUTOPAUSE|MODE_CDDA)) != (MODE_AUTOPAUSE|MODE_CDDA)) return;
-
- // Reschedule IRQ
- if ( cdr.Irq || cdr.Stat ) {
-#ifdef CDR_LOG
- CDR_LOG("=== BUSY === cdrPlayInterrupt\n");
-#endif
+ tmp[0] = itob(time[0]);
+ tmp[1] = itob(time[1]);
+ tmp[2] = itob(time[2]);
- //CDRPLAY_INT( 0x800 );
+ if (memcmp(cdr.Prev, tmp, 3) == 0)
return;
- }
-
- if( CDR_getStatus(&stat) == -1) return;
+ CDR_LOG("ReadTrack *** %02x:%02x:%02x\n", tmp[0], tmp[1], tmp[2]);
- subq = (struct SubQ *)CDR_getBufferSub();
-
- if (subq != NULL ) {
-#ifdef CDR_LOG
- CDR_LOG( "CDDA SUB - %X:%X:%X\n",
- subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] );
-#endif
-
- /*
- CDDA Autopause
-
- Silhouette Mirage ($3)
- Tomb Raider 1 ($7)
- */
-
- if( cdr.CurTrack < btoi( subq->TrackNumber ) ) {
-#ifdef CDR_LOG
- CDR_LOG( "CDDA STOP\n" );
-#endif
-
- // Magic the Gathering
- // - looping territory cdda
-
- // ...?
- //cdr.ResultReady = 1;
- //cdr.Stat = DataReady;
- cdr.Stat = DataEnd;
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+ cdr.RErr = CDR_readTrack(tmp);
+ memcpy(cdr.Prev, tmp, 3);
+ if (CheckSBI(time))
+ return;
- StopCdda();
+ subq = (struct SubQ *)CDR_getBufferSub();
+ if (subq != NULL && cdr.CurTrack == 1) {
+ crc = calcCrc((u8 *)subq + 12, 10);
+ if (crc == (((u16)subq->CRC[0] << 8) | subq->CRC[1])) {
+ cdr.subq.Track = subq->TrackNumber;
+ cdr.subq.Index = subq->IndexNumber;
+ memcpy(cdr.subq.Relative, subq->TrackRelativeAddress, 3);
+ memcpy(cdr.subq.Absolute, subq->AbsoluteAddress, 3);
}
- } else {
-#ifdef CDR_LOG___0
- CDR_LOG( "CDDA FAKE SUB - %d:%d:%d\n",
- temp_cur[0], temp_cur[1], temp_cur[2] );
-#endif
-
- //if( msf2sec(temp_cur) >= msf2sec( temp_next ) ) {
- if( fake_subq_change ) {
-#ifdef CDR_LOG
- CDR_LOG( "CDDA STOP\n" );
-#endif
-
- // Magic the Gathering
- // - looping territory cdda
-
- // ...?
- //cdr.ResultReady = 1;
- //cdr.Stat = DataReady;
- cdr.Stat = DataEnd;
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
-
-
- StopCdda();
-
- fake_subq_change = 0;
+ else {
+ CDR_LOG_I("subq bad crc @%02x:%02x:%02x\n",
+ tmp[0], tmp[1], tmp[2]);
}
}
-}
-
-
-void cdrPlayInterrupt_Repplay()
-{
- // BIOS - HACK: Switch between local / absolute times
- static u8 report_time = 1;
-
-
- if ((cdr.Mode & (MODE_REPORT|MODE_CDDA)) != (MODE_REPORT|MODE_CDDA)) return;
-
-#ifdef CDR_LOG
- CDR_LOG("cdrRepplayInterrupt() Log: KEY END\n");
-#endif
-
- // Doom - no more cdda playing
- // - fixes boot with irq cmd reschedule
-
- // Reschedule IRQ
- if ( cdr.Irq || cdr.Stat ) {
-#ifdef CDR_LOG
- CDR_LOG("=== BUSY === cdrRepplayInterrupt\n");
-#endif
-
- //CDREPPLAY_INT( 0x800 );
- return;
+ else {
+ generate_subq(time);
}
-
-
- memset( cdr.Result, 0, 8 );
- if( CDR_getStatus(&stat) == -1) return;
-
- cdr.Result[0] = cdr.StatP;
-
-
- subq = (struct SubQ *)CDR_getBufferSub();
- if (subq != NULL ) {
-#ifdef CDR_LOG
- CDR_LOG( "REPPLAY SUB - %X:%X:%X\n",
- subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] );
-#endif
+ CDR_LOG(" -> %02x,%02x %02x:%02x:%02x %02x:%02x:%02x\n",
+ cdr.subq.Track, cdr.subq.Index,
+ cdr.subq.Relative[0], cdr.subq.Relative[1], cdr.subq.Relative[2],
+ cdr.subq.Absolute[0], cdr.subq.Absolute[1], cdr.subq.Absolute[2]);
+}
- /*
- skip subQ integrity check (audio playback)
- - mainly useful for DATA LibCrypt checking
- */
- //if( SWAP16(subq->CRC) != calcCrc((unsigned char *)subq + 12, 10) )
-
- // 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;
+static void AddIrqQueue(unsigned char irq, unsigned long ecycle) {
+ if (cdr.Irq != 0)
+ CDR_LOG_I("cdr: override cmd %02x -> %02x\n", cdr.Irq, irq);
- cdr.CurTrack = btoi( subq->TrackNumber );
- }
+ cdr.Irq = irq;
+ cdr.eCycle = ecycle;
+ CDR_INT(ecycle);
+}
- // BIOS CD Player: data already BCD format
- cdr.Result[1] = subq->TrackNumber;
- cdr.Result[2] = subq->IndexNumber;
+static void cdrPlayInterrupt_Autopause()
+{
+ if ((cdr.Mode & MODE_AUTOPAUSE) && cdr.TrackChanged) {
+ CDR_LOG( "CDDA STOP\n" );
+ // Magic the Gathering
+ // - looping territory cdda
- // 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];
+ // ...?
+ //cdr.ResultReady = 1;
+ //cdr.Stat = DataReady;
+ cdr.Stat = DataEnd;
+ setIrq();
- report_time = 1;
- } else {
- cdr.Result[3] = subq->TrackRelativeAddress[0];
- cdr.Result[4] = subq->TrackRelativeAddress[1];
- cdr.Result[5] = subq->TrackRelativeAddress[2];
+ StopCdda();
+ }
+ else if (cdr.Mode & MODE_REPORT) {
- cdr.Result[4] |= 0x80;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Result[1] = cdr.subq.Track;
+ cdr.Result[2] = cdr.subq.Index;
- report_time = 0;
+ if (cdr.subq.Absolute[2] & 0x10) {
+ cdr.Result[3] = cdr.subq.Relative[0];
+ cdr.Result[4] = cdr.subq.Relative[1] | 0x80;
+ cdr.Result[5] = cdr.subq.Relative[2];
}
- } else {
-#ifdef CDR_LOG___0
- CDR_LOG( "REPPLAY FAKE - %d:%d:%d\n",
- temp_cur[0], temp_cur[1], temp_cur[2] );
-#endif
-
- // Rayman: check track change
- //if( msf2sec(temp_cur) >= msf2sec( temp_next ) ) {
- if( fake_subq_change ) {
-#ifdef CDR_LOG___0
- CDR_LOG( "TRACK CHANGE %d - %d %d %d ==> %d %d %d\n",
- cdr.CurTrack,
- temp_cur[0], temp_cur[1], temp_cur[2],
- temp_next[0], temp_next[1], temp_next[2] );
-#endif
-
- cdr.Result[0] |= 0x10;
-
- fake_subq_change = 0;
- }
-
-
- // track # / index #
- cdr.Result[1] = itob(cdr.CurTrack);
- cdr.Result[2] = itob(fake_subq_index);
-
- if( report_time == 0 ) {
- // absolute
- cdr.Result[3] = itob( fake_subq_real[0] );
- cdr.Result[4] = itob( fake_subq_real[1] );
- cdr.Result[5] = itob( fake_subq_real[2] );
-
- report_time = 1;
- } else {
- // local
- cdr.Result[3] = itob( fake_subq_local[0] );
- cdr.Result[4] = itob( fake_subq_local[1] );
- cdr.Result[5] = itob( fake_subq_local[2] );
-
- cdr.Result[4] |= 0x80;
-
- report_time = 0;
+ else {
+ cdr.Result[3] = cdr.subq.Absolute[0];
+ cdr.Result[4] = cdr.subq.Absolute[1];
+ cdr.Result[5] = cdr.subq.Absolute[2];
}
cdr.Result[6] = 0;
cdr.Result[7] = 0;
- }
+ // Rayman: Logo freeze (resultready + dataready)
+ cdr.ResultReady = 1;
+ cdr.Stat = DataReady;
- // Rayman: Logo freeze (resultready + dataready)
- cdr.ResultReady = 1;
- cdr.Stat = DataReady;
-
- SetResultSize(8);
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+ SetResultSize(8);
+ setIrq();
+ }
}
-
+// also handles seek
void cdrPlayInterrupt()
{
- if( !cdr.Play ) return;
-
- //////////////////////////////////////////
- //////////////////////////////////////////
-
-#ifdef CDR_LOG
- CDR_LOG( "CDDA - %d:%d:%d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
-
-
- {
- u8 temp[3];
-
- temp[0] = itob(cdr.SetSectorPlay[0]);
- temp[1] = itob(cdr.SetSectorPlay[1]);
- temp[2] = itob(cdr.SetSectorPlay[2]);
-
- // get subq
- CDR_readTrack( temp );
- }
-
- if( CDR_readCDDA ) {
- CDR_readCDDA( cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], cdr.Transfer );
+ if (cdr.Seeked == SEEK_PENDING) {
+ if (cdr.Stat) {
+ CDRMISC_INT( 0x100 );
+ return;
+ }
+ SetResultSize(1);
+ cdr.StatP |= STATUS_ROTATING;
+ cdr.StatP &= ~STATUS_SEEK;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Seeked = SEEK_DONE;
+ if (cdr.Irq == 0) {
+ cdr.Stat = Complete;
+ setIrq();
+ }
- CDXA_Attenuation( (short *) cdr.Transfer, 2352, 1, CDDA_ATTENUATE );
+ memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
+ Find_CurTrack(cdr.SetSectorPlay);
+ ReadTrack(cdr.SetSectorPlay);
+ cdr.TrackChanged = FALSE;
}
+ if (!cdr.Play) return;
+ CDR_LOG( "CDDA - %d:%d:%d\n",
+ cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
- // mute data track
- if( (Config.Cdda) ||
- (CDR_getStatus(&stat) != -1 && stat.Type == 1 && cdr.CurTrack == 1) )
- memset( cdr.Transfer, 0, CD_FRAMESIZE_RAW );
-
-
- if( SPU_playCDDAchannel)
- SPU_playCDDAchannel((short *)cdr.Transfer, CD_FRAMESIZE_RAW);
-
- CDRPLAY_INT( cdReadTime );
+ if (memcmp(cdr.SetSectorPlay, cdr.SetSectorEnd, 3) == 0) {
+ StopCdda();
+ cdr.TrackChanged = TRUE;
+ }
- //////////////////////////////////////////
- //////////////////////////////////////////
+ if (!cdr.Irq && !cdr.Stat && (cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT)))
+ cdrPlayInterrupt_Autopause();
- subq = (struct SubQ *)CDR_getBufferSub();
- if (subq == NULL )
- Create_Fake_Subq();
+ if (!cdr.Play) return;
- cdrPlayInterrupt_Autopause();
- cdrPlayInterrupt_Repplay();
+ if (CDR_readCDDA && !cdr.Muted && cdr.CurTrack > 1) {
+ CDR_readCDDA(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1],
+ cdr.SetSectorPlay[2], cdr.Transfer);
- //////////////////////////////////////////
- //////////////////////////////////////////
+ cdrAttenuate((s16 *)cdr.Transfer, CD_FRAMESIZE_RAW / 4, 1);
+ if (SPU_playCDDAchannel)
+ SPU_playCDDAchannel((short *)cdr.Transfer, CD_FRAMESIZE_RAW);
+ }
cdr.SetSectorPlay[2]++;
if (cdr.SetSectorPlay[2] == 75) {
@@ -951,11 +678,12 @@ void cdrPlayInterrupt()
}
}
+ CDRMISC_INT(cdReadTime);
- Check_Shell(0);
+ // update for CdlGetlocP/autopause
+ generate_subq(cdr.SetSectorPlay);
}
-
void cdrInterrupt() {
int i;
unsigned char Irq = cdr.Irq;
@@ -966,7 +694,7 @@ void cdrInterrupt() {
return;
}
- cdr.Irq = 0xff;
+ cdr.Irq = 0;
cdr.Ctrl &= ~0x80;
switch (Irq) {
@@ -994,11 +722,33 @@ void cdrInterrupt() {
break;
case CdlPlay:
- fake_subq_change = 0;
-
- if( cdr.Seeked == FALSE ) {
+ if (cdr.Seeked == SEEK_PENDING) {
+ // XXX: wrong, should seek instead..
memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 );
- cdr.Seeked = TRUE;
+ cdr.Seeked = SEEK_DONE;
+ }
+
+ // BIOS CD Player
+ // - Pause player, hit Track 01/02/../xx (Setloc issued!!)
+
+ if (cdr.ParamC == 0 || cdr.Param[0] == 0) {
+ CDR_LOG("PLAY Resume @ %d:%d:%d\n",
+ cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
+ }
+ else
+ {
+ int track = btoi( cdr.Param[0] );
+
+ if (track <= cdr.ResultTN[1])
+ cdr.CurTrack = track;
+
+ CDR_LOG("PLAY track %d\n", cdr.CurTrack);
+
+ if (CDR_getTD((u8)cdr.CurTrack, cdr.ResultTD) != -1) {
+ cdr.SetSectorPlay[0] = cdr.ResultTD[2];
+ cdr.SetSectorPlay[1] = cdr.ResultTD[1];
+ cdr.SetSectorPlay[2] = cdr.ResultTD[0];
+ }
}
/*
@@ -1011,91 +761,16 @@ void cdrInterrupt() {
Wild 9: skip PREGAP + starting accurate SubQ
- plays tracks without retry play
*/
- Set_Track();
- Find_CurTrack();
- ReadTrack( cdr.SetSectorPlay );
-
- // Chronicles of the Sword - getlocp timing
- Create_Fake_Subq();
-
- // 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.Play && CDR_getStatus(&stat) != -1 ) {
- cdr.SetSectorPlay[0] = stat.Time[0];
- cdr.SetSectorPlay[1] = stat.Time[1];
- cdr.SetSectorPlay[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 ) {
-#ifdef CDR_LOG___0
- CDR_LOG( "PLAY Resume @ %d:%d:%d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
-
- //CDR_play( cdr.SetSectorPlay );
- }
- else
- {
- // BIOS CD Player: Resume play
- if( cdr.Param[0] == 0 ) {
-#ifdef CDR_LOG___0
- CDR_LOG( "PLAY Resume T0 @ %d:%d:%d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
-
- //CDR_play( cdr.SetSectorPlay );
- }
- else {
-#ifdef CDR_LOG___0
- CDR_LOG( "PLAY Resume Td @ %d:%d:%d\n",
- cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
-
- // 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.SetSectorPlay[0] = cdr.ResultTD[2];
- cdr.SetSectorPlay[1] = cdr.ResultTD[1];
- cdr.SetSectorPlay[2] = cdr.ResultTD[0];
-
- // reset data
- Set_Track();
- Find_CurTrack();
- ReadTrack( cdr.SetSectorPlay );
-
- //CDR_play(cdr.SetSectorPlay);
- }
- }
- }
- }
- }
+ Find_CurTrack(cdr.SetSectorPlay);
+ ReadTrack(cdr.SetSectorPlay);
+ cdr.TrackChanged = FALSE;
+ if (!Config.Cdda)
+ CDR_play(cdr.SetSectorPlay);
// Vib Ribbon: gameplay checks flag
cdr.StatP &= ~STATUS_SEEK;
-
cdr.CmdProcess = 0;
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
@@ -1108,15 +783,15 @@ void cdrInterrupt() {
// BIOS player - set flag again
cdr.Play = TRUE;
- CDRPLAY_INT( cdReadTime );
+ CDRMISC_INT( cdReadTime );
break;
- case CdlForward:
+ case CdlForward:
cdr.CmdProcess = 0;
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Complete;
// GameShark CD Player: Calls 2x + Play 2x
@@ -1126,12 +801,12 @@ void cdrInterrupt() {
cdr.FastBackward = 0;
break;
- case CdlBackward:
+ case CdlBackward:
cdr.CmdProcess = 0;
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Complete;
// GameShark CD Player: Calls 2x + Play 2x
@@ -1141,7 +816,7 @@ void cdrInterrupt() {
cdr.FastForward = 0;
break;
- case CdlStandby:
+ case CdlStandby:
cdr.CmdProcess = 0;
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
@@ -1164,6 +839,7 @@ void cdrInterrupt() {
SetResultSize(1);
cdr.Result[0] = cdr.StatP;
cdr.Stat = Acknowledge;
+
/*
Gundam Battle Assault 2: much slower (*)
- Fixes boot, gameplay
@@ -1180,17 +856,17 @@ void cdrInterrupt() {
case CdlPause + 0x20:
SetResultSize(1);
- cdr.StatP &= ~STATUS_READ;
+ cdr.StatP &= ~STATUS_READ;
cdr.StatP |= STATUS_ROTATING;
cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
+ cdr.Stat = Complete;
break;
- case CdlInit:
+ case CdlInit:
SetResultSize(1);
- cdr.StatP = STATUS_ROTATING;
+ cdr.StatP = STATUS_ROTATING;
cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
+ cdr.Stat = Acknowledge;
// if (!cdr.Init) {
AddIrqQueue(CdlInit + 0x20, 0x800);
// }
@@ -1199,105 +875,68 @@ void cdrInterrupt() {
case CdlInit + 0x20:
SetResultSize(1);
cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
+ cdr.Stat = Complete;
cdr.Init = 1;
break;
- case CdlMute:
+ case CdlMute:
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Acknowledge;
break;
- case CdlDemute:
+ case CdlDemute:
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Acknowledge;
break;
- case CdlSetfilter:
+ case CdlSetfilter:
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Acknowledge;
+ break;
case CdlSetmode:
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
- break;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Acknowledge;
+ break;
- case CdlGetmode:
+ case CdlGetmode:
SetResultSize(6);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Result[1] = cdr.Mode;
- cdr.Result[2] = cdr.File;
- cdr.Result[3] = cdr.Channel;
- cdr.Result[4] = 0;
- cdr.Result[5] = 0;
- cdr.Stat = Acknowledge;
- break;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Result[1] = cdr.Mode;
+ cdr.Result[2] = cdr.File;
+ cdr.Result[3] = cdr.Channel;
+ cdr.Result[4] = 0;
+ cdr.Result[5] = 0;
+ cdr.Stat = Acknowledge;
+ break;
- case CdlGetlocL:
+ case CdlGetlocL:
SetResultSize(8);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++)
cdr.Result[i] = cdr.Transfer[i];
cdr.Stat = Acknowledge;
- break;
+ break;
case CdlGetlocP:
- // GameShark CDX CD Player: uses 17 bytes output (wraps around)
- SetResultSize(17);
- memset( cdr.Result, 0, 16 );
-
- subq = (struct SubQ *)CDR_getBufferSub();
-
- 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);
-
-
- // subQ integrity check - data only (skip audio)
- if( subq->TrackNumber == 1 && stat.Type == 0x01 ) {
- if (calcCrc((u8 *)subq + 12, 10) != (((u16)subq->CRC[0] << 8) | subq->CRC[1])) {
- memset(cdr.Result + 2, 0, 3 + 3); // CRC wrong, wipe out time data
- }
- }
- } else {
- if( cdr.Play == FALSE ) Create_Fake_Subq();
-
-
- // track # / index #
- cdr.Result[0] = itob(cdr.CurTrack);
- cdr.Result[1] = itob(fake_subq_index);
-
- // local
- cdr.Result[2] = itob( fake_subq_local[0] );
- cdr.Result[3] = itob( fake_subq_local[1] );
- cdr.Result[4] = itob( fake_subq_local[2] );
-
- // absolute
- cdr.Result[5] = itob( fake_subq_real[0] );
- cdr.Result[6] = itob( fake_subq_real[1] );
- cdr.Result[7] = itob( fake_subq_real[2] );
- }
+ SetResultSize(8);
+ memcpy(&cdr.Result, &cdr.subq, 8);
- // redump.org - wipe time
- if( !cdr.Play && CheckSBI(cdr.Result+5) ) {
- memset( cdr.Result+2, 0, 6 );
- }
+ if (!cdr.Play && !cdr.Reading)
+ cdr.Result[1] = 0; // HACK?
cdr.Stat = Acknowledge;
break;
- case CdlGetTN:
+ case CdlGetTN:
// 5-Star Racing: don't stop CDDA
//
// Vib Ribbon: CD swap
@@ -1306,18 +945,18 @@ void cdrInterrupt() {
cdr.CmdProcess = 0;
SetResultSize(3);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- if (CDR_getTN(cdr.ResultTN) == -1) {
+ cdr.Result[0] = cdr.StatP;
+ if (CDR_getTN(cdr.ResultTN) == -1) {
cdr.Stat = DiskError;
cdr.Result[0] |= STATUS_ERROR;
- } else {
- cdr.Stat = Acknowledge;
- cdr.Result[1] = itob(cdr.ResultTN[0]);
- cdr.Result[2] = itob(cdr.ResultTN[1]);
- }
- break;
+ } else {
+ cdr.Stat = Acknowledge;
+ cdr.Result[1] = itob(cdr.ResultTN[0]);
+ cdr.Result[2] = itob(cdr.ResultTN[1]);
+ }
+ break;
- case CdlGetTD:
+ case CdlGetTD:
cdr.CmdProcess = 0;
cdr.Track = btoi(cdr.Param[0]);
SetResultSize(4);
@@ -1334,12 +973,13 @@ void cdrInterrupt() {
}
break;
- case CdlSeekL:
+ case CdlSeekL:
+ case CdlSeekP:
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
+ cdr.Result[0] = cdr.StatP;
cdr.StatP |= STATUS_SEEK;
- cdr.Stat = Acknowledge;
+ cdr.Stat = Acknowledge;
/*
Crusaders of Might and Magic = 0.5x-4x
@@ -1354,51 +994,14 @@ void cdrInterrupt() {
Rockman X5 = 0.5-4x
- fix capcom logo
*/
- AddIrqQueue(CdlSeekL + 0x20, cdReadTime * 4);
- break;
-
- case CdlSeekL + 0x20:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.StatP &= ~STATUS_SEEK;
- cdr.Result[0] = cdr.StatP;
- cdr.Seeked = TRUE;
- cdr.Stat = Complete;
-
-
- // Mega Man Legends 2: must update read cursor for getlocp
- ReadTrack( cdr.SetSector );
- break;
-
- case CdlSeekP:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.StatP |= STATUS_SEEK;
- cdr.Stat = Acknowledge;
- AddIrqQueue(CdlSeekP + 0x20, cdReadTime * 1);
- break;
-
- case CdlSeekP + 0x20:
- SetResultSize(1);
- cdr.StatP |= STATUS_ROTATING;
- cdr.StatP &= ~STATUS_SEEK;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
- cdr.Seeked = TRUE;
-
- // GameShark Music Player
- memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 );
-
- // Tomb Raider 2: must update read cursor for getlocp
- Find_CurTrack();
- ReadTrack( cdr.SetSectorPlay );
+ CDRMISC_INT(cdr.Seeked == SEEK_DONE ? 0x800 : cdReadTime * 4);
+ cdr.Seeked = SEEK_PENDING;
break;
case CdlTest:
- cdr.Stat = Acknowledge;
- switch (cdr.Param[0]) {
- case 0x20: // System Controller ROM Version
+ cdr.Stat = Acknowledge;
+ switch (cdr.Param[0]) {
+ case 0x20: // System Controller ROM Version
SetResultSize(4);
memcpy(cdr.Result, Test20, 4);
break;
@@ -1410,14 +1013,14 @@ void cdrInterrupt() {
SetResultSize(8);
memcpy(cdr.Result, Test23, 4);
break;
- }
+ }
break;
- case CdlID:
+ case CdlID:
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Acknowledge;
AddIrqQueue(CdlID + 0x20, 0x800);
break;
@@ -1457,9 +1060,9 @@ void cdrInterrupt() {
case CdlReset:
SetResultSize(1);
- cdr.StatP = STATUS_ROTATING;
+ cdr.StatP = STATUS_ROTATING;
cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
+ cdr.Stat = Acknowledge;
break;
case CdlReadT:
@@ -1477,59 +1080,46 @@ void cdrInterrupt() {
cdr.Stat = Complete;
break;
- case CdlReadToc:
+ case CdlReadToc:
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Acknowledge;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Acknowledge;
AddIrqQueue(CdlReadToc + 0x20, 0x800);
break;
- case CdlReadToc + 0x20:
+ case CdlReadToc + 0x20:
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = Complete;
- break;
-
- case AUTOPAUSE:
- cdr.OCUP = 0;
-/* SetResultSize(1);
- StopCdda();
- StopReading();
- cdr.OCUP = 0;
- cdr.StatP&=~0x20;
- cdr.StatP|= 0x2;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = DataEnd;
-*/ AddIrqQueue(CdlPause, 0x800);
+ cdr.Result[0] = cdr.StatP;
+ cdr.Stat = Complete;
break;
- case READ_ACK:
+ case CdlReadN:
+ case CdlReadS:
if (!cdr.Reading) return;
-
// Fighting Force 2 - update subq time immediately
// - fixes new game
- ReadTrack( cdr.SetSector );
+ Find_CurTrack(cdr.SetSector);
+ ReadTrack(cdr.SetSector);
// Crusaders of Might and Magic - update getlocl now
// - fixes cutscene speech
{
u8 *buf = CDR_getBuffer();
- memcpy(cdr.Transfer, buf, 8);
+ if (buf != NULL)
+ memcpy(cdr.Transfer, buf, 8);
}
-
-
+
/*
Duke Nukem: Land of the Babes - seek then delay read for one frame
- fixes cutscenes
+ C-12 - Final Resistance - doesn't like seek
*/
- if (!cdr.Seeked) {
- cdr.Seeked = TRUE;
-
+ if (cdr.Seeked != SEEK_DONE) {
cdr.StatP |= STATUS_SEEK;
cdr.StatP &= ~STATUS_READ;
@@ -1551,9 +1141,6 @@ void cdrInterrupt() {
cdr.Stat = Acknowledge;
break;
- case 0xff:
- return;
-
default:
cdr.Stat = Complete;
break;
@@ -1561,15 +1148,62 @@ void cdrInterrupt() {
Check_Shell( Irq );
- if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) {
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
- }
+ cdr.ParamC = 0;
+
+ setIrq();
-#ifdef CDR_LOG
- CDR_LOG("cdrInterrupt() Log: CDR Interrupt IRQ %x\n", Irq);
+#ifdef CDR_LOG_CMD_IRQ
+ SysPrintf("cdrInterrupt() Log: CDR Interrupt IRQ %d %02x: ",
+ cdr.Stat != NoIntr && cdr.Reg2 != 0x18, Irq);
+ for (i = 0; i < cdr.ResultC; i++)
+ SysPrintf("%02x ", cdr.Result[i]);
+ SysPrintf("\n");
#endif
}
+#define ssat32_to_16(v) do { \
+ if (v < -32768) v = -32768; \
+ else if (v > 32767) v = 32767; \
+} while (0)
+
+void cdrAttenuate(s16 *buf, int samples, int stereo)
+{
+ int i, l, r;
+ int ll = cdr.AttenuatorLeftToLeft;
+ int lr = cdr.AttenuatorLeftToRight;
+ int rl = cdr.AttenuatorRightToLeft;
+ int rr = cdr.AttenuatorRightToRight;
+
+ if (lr == 0 && rl == 0 && 0x78 <= ll && ll <= 0x88 && 0x78 <= rr && rr <= 0x88)
+ return;
+
+ if (!stereo && ll == 0x40 && lr == 0x40 && rl == 0x40 && rr == 0x40)
+ return;
+
+ if (stereo) {
+ for (i = 0; i < samples; i++) {
+ l = buf[i * 2];
+ r = buf[i * 2 + 1];
+ l = (l * ll + r * rl) >> 7;
+ r = (r * rr + l * lr) >> 7;
+ ssat32_to_16(l);
+ ssat32_to_16(r);
+ buf[i * 2] = l;
+ buf[i * 2 + 1] = r;
+ }
+ }
+ else {
+ for (i = 0; i < samples; i++) {
+ l = buf[i];
+ l = l * (ll + rl) >> 7;
+ //r = r * (rr + lr) >> 7;
+ ssat32_to_16(l);
+ //ssat32_to_16(r);
+ buf[i] = l;
+ }
+ }
+}
+
void cdrReadInterrupt() {
u8 *buf;
@@ -1581,26 +1215,21 @@ void cdrReadInterrupt() {
return;
}
-#ifdef CDR_LOG
- CDR_LOG("cdrReadInterrupt() Log: KEY END");
-#endif
-
- cdr.OCUP = 1;
+ cdr.OCUP = 1;
SetResultSize(1);
cdr.StatP |= STATUS_READ|STATUS_ROTATING;
cdr.StatP &= ~STATUS_SEEK;
- cdr.Result[0] = cdr.StatP;
+ cdr.Result[0] = cdr.StatP;
+ cdr.Seeked = SEEK_DONE;
- ReadTrack( cdr.SetSector );
+ ReadTrack(cdr.SetSector);
buf = CDR_getBuffer();
if (buf == NULL)
cdr.RErr = -1;
if (cdr.RErr == -1) {
-#ifdef CDR_LOG
- fprintf(emuLog, "cdrReadInterrupt() Log: err\n");
-#endif
+ CDR_LOG_I("cdrReadInterrupt() Log: err\n");
memset(cdr.Transfer, 0, DATA_SIZE);
cdr.Stat = DiskError;
cdr.Result[0] |= STATUS_ERROR;
@@ -1612,9 +1241,7 @@ void cdrReadInterrupt() {
CheckPPFCache(cdr.Transfer, cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]);
-#ifdef CDR_LOG
- fprintf(emuLog, "cdrReadInterrupt() Log: cdr.Transfer %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]);
-#endif
+ CDR_LOG("cdrReadInterrupt() Log: cdr.Transfer %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]);
if ((!cdr.Muted) && (cdr.Mode & MODE_STRSND) && (!Config.Xa) && (cdr.FirstSector != -1)) { // CD-XA
// Firemen 2: Multi-XA files - briefings, cutscenes
@@ -1627,96 +1254,49 @@ void cdrReadInterrupt() {
(cdr.Transfer[4 + 1] == cdr.Channel) &&
(cdr.Transfer[4 + 0] == cdr.File)) {
int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector);
-
if (!ret) {
-#if 0
- int xa_type;
-
- // save - set only for FirstSector
- xa_type = cdr.Xa.stereo;
-
-
- // Duke Nukem - Time to Kill - speech, music volume control
- // Tekken 3 - post-match fade out
- if( cdr.Xa.stereo == 0 )
- CDXA_Attenuation( cdr.Xa.pcm, cdr.Xa.nsamples * 2, cdr.Xa.stereo, XA_ATTENUATE );
- else
- CDXA_Attenuation( cdr.Xa.pcm, cdr.Xa.nsamples * 4, cdr.Xa.stereo, XA_ATTENUATE );
-
-
- // fix mono xa attenuation
- if( cdr.Xa.stereo == 0 ) cdr.Xa.stereo = 1;
-#endif
-
+ cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo);
SPU_playADPCMchannel(&cdr.Xa);
cdr.FirstSector = 0;
-
-
-#if 0
- cdr.Xa.stereo = xa_type;
-#endif
-
-
-#if 0
- // Crash Team Racing: music, speech
- // - done using cdda decoded buffer (spu irq)
- // - don't do here
-
- // signal ADPCM data ready
- psxHu32ref(0x1070) |= SWAP32((u32)0x200);
-#endif
}
else cdr.FirstSector = -1;
}
}
cdr.SetSector[2]++;
- if (cdr.SetSector[2] == 75) {
- cdr.SetSector[2] = 0;
- cdr.SetSector[1]++;
- if (cdr.SetSector[1] == 60) {
- cdr.SetSector[1] = 0;
- cdr.SetSector[0]++;
- }
- }
-
- cdr.Readed = 0;
-
- // G-Police: Don't autopause ADPCM even if mode set (music)
- if ((cdr.Transfer[4 + 2] & 0x80) && (cdr.Mode & MODE_AUTOPAUSE) &&
- (cdr.Transfer[4 + 2] & 0x4) != 0x4 ) { // EOF
-#ifdef CDR_LOG
- CDR_LOG("cdrReadInterrupt() Log: Autopausing read\n");
-#endif
-// AddIrqQueue(AUTOPAUSE, 0x2000);
- AddIrqQueue(CdlPause, 0x2000);
- }
- else {
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
+ if (cdr.SetSector[2] == 75) {
+ cdr.SetSector[2] = 0;
+ cdr.SetSector[1]++;
+ if (cdr.SetSector[1] == 60) {
+ cdr.SetSector[1] = 0;
+ cdr.SetSector[0]++;
+ }
}
+ cdr.Readed = 0;
+
+ CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
+
/*
Croc 2: $40 - only FORM1 (*)
Judge Dredd: $C8 - only FORM1 (*)
Sim Theme Park - no adpcm at all (zero)
*/
- if( (cdr.Mode & MODE_STRSND) == 0 || (cdr.Transfer[4+2] & 0x4) != 0x4 ) {
- cdr.Stat = DataReady;
- } else {
- // Breath of Fire 3 - fix inn sleeping
- // Rockman X5 - no music restart problem
- cdr.Stat = NoIntr;
- }
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+ if (!(cdr.Mode & MODE_STRSND) || !(cdr.Transfer[4+2] & 0x4)) {
+ cdr.Stat = DataReady;
+ setIrq();
+ }
+
+ // update for CdlGetlocP
+ ReadTrack(cdr.SetSector);
Check_Shell(0);
}
/*
cdrRead0:
- bit 0 - 0 REG1 command send / 1 REG1 data read
- bit 1 - 0 data transfer finish / 1 data transfer ready/in progress
+ bit 0,1 - mode
bit 2 - unknown
bit 3 - unknown
bit 4 - unknown
@@ -1739,77 +1319,51 @@ unsigned char cdrRead0(void) {
// What means the 0x10 and the 0x08 bits? I only saw it used by the bios
cdr.Ctrl |= 0x18;
-#ifdef CDR_LOG
- CDR_LOG("cdrRead0() Log: CD0 Read: %x\n", cdr.Ctrl);
-#endif
+ CDR_LOG_IO("cdr r0: %02x\n", cdr.Ctrl);
return psxHu8(0x1800) = cdr.Ctrl;
}
-/*
-cdrWrite0:
- 0 - to send a command / 1 - to get the result
-*/
-
void cdrWrite0(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite0() Log: CD0 write: %x\n", rt);
-#endif
- cdr.Ctrl = rt | (cdr.Ctrl & ~0x3);
-
- if (rt == 0) {
- cdr.ParamP = 0;
- cdr.ParamC = 0;
- cdr.ResultReady = 0;
- }
+ CDR_LOG_IO("cdr w0: %02x\n", rt);
- // Tekken: CDXA fade-out
- else if( rt == 2 ) {
- //cdr.AttenuatorLeft[0] = 0;
- //cdr.AttenuatorLeft[1] = 0;
- }
- else if( rt == 3 ) {
- // Tekken 3 - character menu (don't do this!)
- //cdr.AttenuatorRight[0] = 0;
- //cdr.AttenuatorRight[1] = 0;
- }
+ cdr.Ctrl = (rt & 3) | (cdr.Ctrl & ~3);
}
unsigned char cdrRead1(void) {
- if (cdr.ResultReady) { // && cdr.Ctrl & 0x1) {
- // GameShark CDX CD Player: uses 17 bytes output (wraps around)
+ if ((cdr.ResultP & 0xf) < cdr.ResultC)
psxHu8(0x1801) = cdr.Result[cdr.ResultP & 0xf];
- cdr.ResultP++;
- if (cdr.ResultP == cdr.ResultC)
- cdr.ResultReady = 0;
- } else {
+ else
psxHu8(0x1801) = 0;
- }
-#ifdef CDR_LOG
- CDR_LOG("cdrRead1() Log: CD1 Read: %x\n", psxHu8(0x1801));
-#endif
+ cdr.ResultP++;
+ if (cdr.ResultP == cdr.ResultC)
+ cdr.ResultReady = 0;
+
+ CDR_LOG_IO("cdr r1: %02x\n", psxHu8(0x1801));
+
return psxHu8(0x1801);
}
void cdrWrite1(unsigned char rt) {
+ u8 set_loc[3];
int i;
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite1() Log: CD1 write: %x (%s)\n", rt, CmdName[rt]);
-#endif
-
+ CDR_LOG_IO("cdr w1: %02x\n", rt);
- // Tekken: CDXA fade-out
- if( (cdr.Ctrl & 3) == 3 ) {
- cdr.AttenuatorRight[0] = rt;
+ switch (cdr.Ctrl & 3) {
+ case 0:
+ break;
+ case 3:
+ cdr.AttenuatorRightToRightT = rt;
+ return;
+ default:
+ return;
}
-
- // psxHu8(0x1801) = rt;
- cdr.Cmd = rt;
+ cdr.Cmd = rt;
cdr.OCUP = 0;
-#ifdef CDRCMD_DEBUG
+#ifdef CDR_LOG_CMD_IRQ
SysPrintf("cdrWrite1() Log: CD1 write: %x (%s)", rt, CmdName[rt]);
if (cdr.ParamC) {
SysPrintf(" Param[%d] = {", cdr.ParamC);
@@ -1821,309 +1375,162 @@ void cdrWrite1(unsigned char rt) {
}
#endif
- if (cdr.Ctrl & 0x1) return;
-
- switch (cdr.Cmd) {
- case CdlSync:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlNop:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // Twisted Metal 3 - fix music
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlSetloc:
- 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, 0x800);
- break;
-
- case CdlPlay:
- // Vib Ribbon: try same track again
- StopCdda();
-
- // Vib Ribbon - decoded buffer IRQ for CDDA reading
- // - fixes ribbon timing + music CD mode
- CDRDBUF_INT( PSXCLK / 44100 * 0x100 );
-
-
- cdr.Play = TRUE;
-
- cdr.StatP |= STATUS_SEEK;
- cdr.StatP &= ~STATUS_ROTATING;
-
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlForward:
- //if (cdr.CurTrack < 0xaa)
- // cdr.CurTrack++;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlBackward:
- //if (cdr.CurTrack > 1)
- //cdr.CurTrack--;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlReadN:
- cdr.Irq = 0;
- StopReading();
- cdr.Ctrl|= 0x80;
- cdr.Stat = NoIntr;
- StartReading(1, 0x800);
- break;
-
- case CdlStandby:
- StopCdda();
- StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
+ cdr.ResultReady = 0;
+ cdr.Ctrl |= 0x80;
+ // cdr.Stat = NoIntr;
+ AddIrqQueue(cdr.Cmd, 0x800);
+
+ switch (cdr.Cmd) {
+ case CdlSync:
+ case CdlNop:
+ case CdlForward:
+ case CdlBackward:
+ case CdlReadT:
+ case CdlTest:
+ case CdlID:
+ case CdlReadToc:
+ case CdlGetmode:
+ case CdlGetlocL:
+ case CdlGetlocP:
+ case CdlGetTD:
+ break;
+
+ case CdlSetloc:
+ StopReading();
+ for (i = 0; i < 3; i++)
+ set_loc[i] = btoi(cdr.Param[i]);
+
+ // FIXME: clean up this SetSector/SetSectorPlay mess,
+ // there should be single var tracking current sector pos
+ if (cdr.Play)
+ i = msf2sec(cdr.SetSectorPlay);
+ else
+ i = msf2sec(cdr.SetSector);
+ i = abs(i - msf2sec(set_loc));
+ if (i > 16)
+ cdr.Seeked = SEEK_PENDING;
- case CdlStop:
- // GameShark CD Player: Reset CDDA to track start
- if( cdr.Play && CDR_getStatus(&stat) != -1 ) {
- cdr.SetSectorPlay[0] = stat.Time[0];
- cdr.SetSectorPlay[1] = stat.Time[1];
- cdr.SetSectorPlay[2] = stat.Time[2];
+ memcpy(cdr.SetSector, set_loc, 3);
+ cdr.SetSector[3] = 0;
+ break;
- Find_CurTrack();
+ case CdlPlay:
+ // Vib Ribbon: try same track again
+ StopCdda();
+ // Vib Ribbon - decoded buffer IRQ for CDDA reading
+ // - fixes ribbon timing + music CD mode
+ //CDRDBUF_INT( PSXCLK / 44100 * 0x100 );
- // grab time for current track
- CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD);
+ cdr.Play = TRUE;
- cdr.SetSectorPlay[0] = cdr.ResultTD[2];
- cdr.SetSectorPlay[1] = cdr.ResultTD[1];
- cdr.SetSectorPlay[2] = cdr.ResultTD[0];
- }
+ cdr.StatP |= STATUS_SEEK;
+ cdr.StatP &= ~STATUS_ROTATING;
+ break;
- StopCdda();
- StopReading();
+ case CdlReadN:
+ StopReading();
+ cdr.Reading = 1;
+ cdr.FirstSector = 1;
+ cdr.Readed = 0xff;
+ break;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
+ case CdlStandby:
+ StopCdda();
+ StopReading();
+ break;
+
+ case CdlStop:
+ // GameShark CD Player: Reset CDDA to track start
+ if (cdr.Play) {
+ // grab time for current track
+ CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD);
+
+ cdr.SetSectorPlay[0] = cdr.ResultTD[2];
+ cdr.SetSectorPlay[1] = cdr.ResultTD[1];
+ cdr.SetSectorPlay[2] = cdr.ResultTD[0];
+ }
- case CdlPause:
- /*
- GameShark CD Player: save time for resume
+ StopCdda();
+ StopReading();
+ break;
- Twisted Metal - World Tour: don't mix Setloc / CdlPlay cursors
- */
+ case CdlPause:
+ /*
+ GameShark CD Player: save time for resume
- StopCdda();
- StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
+ Twisted Metal - World Tour: don't mix Setloc / CdlPlay cursors
+ */
- case CdlReset:
- case CdlInit:
- StopCdda();
- StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
+ StopCdda();
+ StopReading();
+ break;
- case CdlMute:
- cdr.Muted = TRUE;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
+ case CdlReset:
+ case CdlInit:
+ cdr.Seeked = SEEK_DONE;
+ StopCdda();
+ StopReading();
+ break;
+ case CdlMute:
+ cdr.Muted = TRUE;
// Duke Nukem - Time to Kill
// - do not directly set cd-xa volume
//SPU_writeRegister( H_CDLeft, 0x0000 );
//SPU_writeRegister( H_CDRight, 0x0000 );
- break;
+ break;
- case CdlDemute:
- cdr.Muted = FALSE;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
+ case CdlDemute:
+ cdr.Muted = FALSE;
// Duke Nukem - Time to Kill
// - do not directly set cd-xa volume
//SPU_writeRegister( H_CDLeft, 0x7f00 );
//SPU_writeRegister( H_CDRight, 0x7f00 );
- break;
+ break;
case CdlSetfilter:
cdr.File = cdr.Param[0];
cdr.Channel = cdr.Param[1];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
break;
case CdlSetmode:
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite1() Log: Setmode %x\n", cdr.Param[0]);
-#endif
- cdr.Mode = cdr.Param[0];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
+ CDR_LOG("cdrWrite1() Log: Setmode %x\n", cdr.Param[0]);
- // Squaresoft on PlayStation 1998 Collector's CD Vol. 1
- // - fixes choppy movie sound
- if( cdr.Play && (cdr.Mode & MODE_CDDA) == 0 )
- StopCdda();
- break;
+ cdr.Mode = cdr.Param[0];
- case CdlGetmode:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
+ // Squaresoft on PlayStation 1998 Collector's CD Vol. 1
+ // - fixes choppy movie sound
+ if( cdr.Play && (cdr.Mode & MODE_CDDA) == 0 )
+ StopCdda();
break;
- case CdlGetlocL:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // Crusaders of Might and Magic - cutscene speech
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlGetlocP:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // GameShark CDX / Lite Player: pretty narrow time window
- // - doesn't always work due to time inprecision
- //AddIrqQueue(cdr.Cmd, 0x28);
-
- // Tomb Raider 2 - cdda
- AddIrqQueue(cdr.Cmd, 0x40);
- break;
-
case CdlGetTN:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- //AddIrqQueue(cdr.Cmd, 0x800);
+ //AddIrqQueue(cdr.Cmd, 0x800);
- // GameShark CDX CD Player: very long time
- AddIrqQueue(cdr.Cmd, 0x100000);
- break;
-
- case CdlGetTD:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
+ // GameShark CDX CD Player: very long time
+ AddIrqQueue(cdr.Cmd, 0x100000);
+ break;
case CdlSeekL:
-// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
-
- StopCdda();
- StopReading();
-
- break;
-
case CdlSeekP:
-// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // Tomb Raider 2 - reset cdda
- StopCdda();
- StopReading();
-
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- // Destruction Derby: read TOC? GetTD after this
- case CdlReadT:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlTest:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlID:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
+ // Tomb Raider 2 - reset cdda
+ StopCdda();
+ StopReading();
+ break;
case CdlReadS:
- cdr.Irq = 0;
- StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- StartReading(2, 0x800);
- break;
+ StopReading();
+ cdr.Reading = 2;
+ cdr.FirstSector = 1;
+ cdr.Readed = 0xff;
+ break;
- case CdlReadToc:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- default:
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd);
-#endif
- return;
- }
- if (cdr.Stat != NoIntr) {
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+ default:
+ cdr.ParamC = 0;
+ CDR_LOG_I("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd);
+ return;
}
}
@@ -2138,123 +1545,67 @@ unsigned char cdrRead2(void) {
adjustTransferIndex();
}
-#ifdef CDR_LOG
- CDR_LOG("cdrRead2() Log: CD2 Read: %x\n", ret);
-#endif
+ CDR_LOG_IO("cdr r2: %02x\n", ret);
return ret;
}
void cdrWrite2(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite2() Log: CD2 write: %x\n", rt);
-#endif
-
-
- // Tekken: CDXA fade-out
- if( (cdr.Ctrl & 3) == 2 ) {
- cdr.AttenuatorLeft[0] = rt;
- }
- else if( (cdr.Ctrl & 3) == 3 ) {
- cdr.AttenuatorRight[1] = rt;
- }
-
+ CDR_LOG_IO("cdr w2: %02x\n", rt);
-
- if (cdr.Ctrl & 0x1) {
- switch (rt) {
- case 0x07:
- cdr.ParamP = 0;
- cdr.ParamC = 0;
- cdr.ResultReady = 1; //0;
- cdr.Ctrl &= ~3; //cdr.Ctrl = 0;
- break;
-
- default:
- cdr.Reg2 = rt;
- break;
- }
- } else if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) {
- cdr.Param[cdr.ParamP++] = rt;
- cdr.ParamC++;
+ switch (cdr.Ctrl & 3) {
+ case 0:
+ if (cdr.ParamC < 8) // FIXME: size and wrapping
+ cdr.Param[cdr.ParamC++] = rt;
+ return;
+ case 1:
+ cdr.Reg2 = rt;
+ setIrq();
+ return;
+ case 2:
+ cdr.AttenuatorLeftToLeftT = rt;
+ return;
+ case 3:
+ cdr.AttenuatorRightToLeftT = rt;
+ return;
}
}
unsigned char cdrRead3(void) {
- if (cdr.Stat) {
- if (cdr.Ctrl & 0x1)
- psxHu8(0x1803) = cdr.Stat | 0xE0;
- else
- psxHu8(0x1803) = 0xff;
- } else {
- psxHu8(0x1803) = 0;
- }
-#ifdef CDR_LOG
- CDR_LOG("cdrRead3() Log: CD3 Read: %x\n", psxHu8(0x1803));
-#endif
+ if (cdr.Ctrl & 0x1)
+ psxHu8(0x1803) = cdr.Stat | 0xE0;
+ else
+ psxHu8(0x1803) = cdr.Reg2 | 0xE0;
+
+ CDR_LOG_IO("cdr r3: %02x\n", psxHu8(0x1803));
return psxHu8(0x1803);
}
void cdrWrite3(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite3() Log: CD3 write: %x\n", rt);
-#endif
+ CDR_LOG_IO("cdr w3: %02x\n", rt);
- // Tekken: CDXA fade-out
- if( (cdr.Ctrl & 3) == 2 ) {
- cdr.AttenuatorLeft[1] = rt;
- }
- else if( (cdr.Ctrl & 3) == 3 && rt == 0x20 ) {
-#ifdef CDR_LOG
- CDR_LOG( "CD-XA Volume: %X %X | %X %X\n",
- cdr.AttenuatorLeft[0], cdr.AttenuatorLeft[1],
- cdr.AttenuatorRight[0], cdr.AttenuatorRight[1] );
-#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;
+ switch (cdr.Ctrl & 3) {
+ case 0:
+ break; // transfer
+ case 1:
+ cdr.Stat &= ~rt;
- if (cdr.Irq == 0xff) {
- cdr.Irq = 0;
- return;
- }
-
-#if 1
- // Brave Fencer Musashi, Micro Machines V3, Parasite Eve 2, etc.
- if (cdr.Reading && !cdr.ResultReady) {
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
- }
-#else
- // XA streaming - incorrect timing because of this reschedule
- // - Final Fantasy Tactics
- // - various other games
-
- /*
- if (cdr.Reading && !cdr.ResultReady) {
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
+ if (rt & 0x40)
+ cdr.ParamC = 0;
+ return;
+ case 2:
+ cdr.AttenuatorLeftToRightT = rt;
+ return;
+ case 3:
+ if (rt & 0x20) {
+ memcpy(&cdr.AttenuatorLeftToLeft, &cdr.AttenuatorLeftToLeftT, 4);
+ CDR_LOG_I("CD-XA Volume: %02x %02x | %02x %02x\n",
+ cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight,
+ cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight);
}
- */
-#endif
-
return;
}
- if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) {
+ if ((rt & 0x80) && cdr.Readed == 0) {
cdr.Readed = 1;
cdr.transferIndex = 0;
@@ -2276,19 +1627,16 @@ void cdrWrite3(unsigned char rt) {
void psxDma3(u32 madr, u32 bcr, u32 chcr) {
u32 cdsize;
- u8 *ptr/*, *cdwrap_ptr*/;
+ int i;
+ u8 *ptr;
-#ifdef CDR_LOG
CDR_LOG("psxDma3() Log: *** DMA 3 *** %x addr = %x size = %x\n", chcr, madr, bcr);
-#endif
switch (chcr) {
case 0x11000000:
case 0x11400100:
if (cdr.Readed == 0) {
-#ifdef CDR_LOG
CDR_LOG("psxDma3() Log: *** DMA 3 *** NOT READY\n");
-#endif
break;
}
@@ -2301,6 +1649,7 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) {
switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
case MODE_SIZE_2340: cdsize = 2340; break;
case MODE_SIZE_2328: cdsize = 2328; break;
+ default:
case MODE_SIZE_2048: cdsize = 2048; break;
}
}
@@ -2308,105 +1657,27 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) {
ptr = (u8 *)PSXM(madr);
if (ptr == NULL) {
-#ifdef CPU_LOG
CDR_LOG("psxDma3() Log: *** DMA 3 *** NULL Pointer!\n");
-#endif
break;
}
-/*
-#if 1
-
- // GS CDX: Enhancement CD crash
- // - Setloc 0:0:0
- // - CdlPlay
- // - Spams DMA3 and gets buffer overrun
-
- if( (cdr.pTransfer-cdr.Transfer) + cdsize > 2352 )
- {
- // avoid crash - probably should wrap here
- //memcpy(ptr, cdr.pTransfer, cdsize);
- }
- else
- {
- memcpy(ptr, cdr.pTransfer, cdsize);
+ /*
+ GS CDX: Enhancement CD crash
+ - Setloc 0:0:0
+ - CdlPlay
+ - Spams DMA3 and gets buffer overrun
+ */
+ for(i = 0; i < cdsize; ++i) {
+ ptr[i] = cdr.Transfer[cdr.transferIndex];
+ cdr.transferIndex++;
+ adjustTransferIndex();
}
psxCpu->Clear(madr, cdsize / 4);
- cdr.pTransfer += cdsize;
-#else
- cdwrap_ptr = cdr.Transfer;
- switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
- case MODE_SIZE_2340: cdwrap_ptr += 2340; break;
- case MODE_SIZE_2328: cdwrap_ptr += 12 + 2328; break;
- case MODE_SIZE_2048: cdwrap_ptr += 12 + 2048; break;
- }
-
-
- // fast copy - no wrap
- if( cdr.pTransfer + cdsize <= cdwrap_ptr ) {
- memcpy(ptr, cdr.pTransfer, cdsize);
-
- psxCpu->Clear(madr, cdsize / 4);
- cdr.pTransfer += cdsize;
- } else {
- int lcv;
-
- // CDROM wrapping
- //
- // Ape Escape - used several times
- // Gameshark Lite - opening movie
- //
- // Gameshark CDX: enhancement CD patcher
- // - calls CdlPlay @ 0:2:0
- // - spams DMA3 and overruns buffer
-
- for( lcv = 0; lcv < cdsize; lcv++ )
- {
- // wrap cdrom ptr
- if( cdr.pTransfer == cdwrap_ptr ) {
- switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
- case MODE_SIZE_2328:
- case MODE_SIZE_2048:
- cdr.pTransfer = cdr.Transfer + 12;
- break;
-
- case MODE_SIZE_2340:
- cdr.pTransfer = cdr.Transfer + 0;
- break;
- }
- }
-
-
- *(ptr+lcv) = *cdr.pTransfer;
-
- cdr.pTransfer++;
- }
-
- psxCpu->Clear(madr, cdsize / 4);
- }
-#endif
-*/
- {
- int i;
-
- for(i = 0; i < cdsize; ++i) {
- ptr[i] = cdr.Transfer[cdr.transferIndex];
- cdr.transferIndex++;
- adjustTransferIndex();
- }
-
- psxCpu->Clear(madr, cdsize / 4);
- }
// burst vs normal
if( chcr == 0x11400100 ) {
-#if 1
CDRDMA_INT( (cdsize/4) / 4 );
-#else
- // Experimental burst dma transfer (0.333x max)
- CDRDMA_INT( (cdsize/4) / 3 );
-#endif
}
else if( chcr == 0x11000000 ) {
CDRDMA_INT( (cdsize/4) * 1 );
@@ -2414,9 +1685,7 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) {
return;
default:
-#ifdef CDR_LOG
CDR_LOG("psxDma3() Log: Unknown cddma %x\n", chcr);
-#endif
break;
}
@@ -2426,8 +1695,22 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) {
void cdrDmaInterrupt()
{
- HW_DMA3_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(3);
+ if (HW_DMA3_CHCR & SWAP32(0x01000000))
+ {
+ HW_DMA3_CHCR &= SWAP32(~0x01000000);
+ DMA_INTERRUPT(3);
+ }
+}
+
+static void getCdInfo(void)
+{
+ u8 tmp;
+
+ CDR_getTN(cdr.ResultTN);
+ CDR_getTD(0, cdr.SetSectorEnd);
+ tmp = cdr.SetSectorEnd[0];
+ cdr.SetSectorEnd[0] = cdr.SetSectorEnd[2];
+ cdr.SetSectorEnd[2] = tmp;
}
void cdrReset() {
@@ -2435,36 +1718,42 @@ void cdrReset() {
cdr.CurTrack = 1;
cdr.File = 1;
cdr.Channel = 1;
+ cdr.transferIndex = 0;
-#if 1
// BIOS player - default values
- cdr.AttenuatorLeft[0] = 0x80;
- cdr.AttenuatorLeft[1] = 0x00;
- cdr.AttenuatorRight[0] = 0x80;
- cdr.AttenuatorRight[1] = 0x00;
-#endif
+ cdr.AttenuatorLeftToLeft = 0x80;
+ cdr.AttenuatorLeftToRight = 0x00;
+ cdr.AttenuatorRightToLeft = 0x00;
+ cdr.AttenuatorRightToRight = 0x80;
+
+ getCdInfo();
}
int cdrFreeze(gzFile f, int Mode) {
- unsigned int tmp;
+ u8 tmpp[3];
-
- if( Mode == 0 ) {
- StopCdda();
- }
-
+ if (Mode == 0 && !Config.Cdda)
+ CDR_stop();
gzfreeze(&cdr, sizeof(cdr));
-
-
if (Mode == 1)
- tmp = cdr.transferIndex;
+ cdr.ParamP = cdr.ParamC;
- gzfreeze(&tmp, sizeof(tmp));
+ if (Mode == 0) {
+ getCdInfo();
- if (Mode == 0)
- cdr.transferIndex = tmp;
+ // read right sub data
+ memcpy(tmpp, cdr.Prev, 3);
+ cdr.Prev[0]++;
+ ReadTrack(tmpp);
+
+ if (cdr.Play) {
+ Find_CurTrack(cdr.SetSectorPlay);
+ if (!Config.Cdda)
+ CDR_play(cdr.SetSectorPlay);
+ }
+ }
return 0;
}
@@ -2472,8 +1761,11 @@ int cdrFreeze(gzFile f, int Mode) {
void LidInterrupt() {
cdr.LidCheck = 0x20; // start checker
+ getCdInfo();
+
+ StopCdda();
CDRLID_INT( cdReadTime * 3 );
-
+
// generate interrupt if none active - open or close
if (cdr.Irq == 0 || cdr.Irq == 0xff) {
cdr.Ctrl |= 0x80;
diff --git a/libpcsxcore/cdrom.h b/libpcsxcore/cdrom.h
index 943564e2..c0534e71 100755
--- a/libpcsxcore/cdrom.h
+++ b/libpcsxcore/cdrom.h
@@ -70,7 +70,7 @@ typedef struct {
unsigned char ResultTN[6];
unsigned char ResultTD[4];
unsigned char SetSector[4];
- unsigned char SetSectorSeek[4];
+ unsigned char SetSectorEnd[4];
unsigned char SetSectorPlay[4];
unsigned char Track;
boolean Play, Muted;
@@ -87,24 +87,38 @@ typedef struct {
unsigned char Irq;
u32 eCycle;
- boolean Seeked;
+ u8 Seeked;
u8 LidCheck;
u8 FastForward;
u8 FastBackward;
- u8 AttenuatorLeft[2], AttenuatorRight[2];
+ u8 AttenuatorLeftToLeft, AttenuatorLeftToRight;
+ u8 AttenuatorRightToRight, AttenuatorRightToLeft;
+ u8 AttenuatorLeftToLeftT, AttenuatorLeftToRightT;
+ u8 AttenuatorRightToRightT, AttenuatorRightToLeftT;
+
+ struct {
+ unsigned char Track;
+ unsigned char Index;
+ unsigned char Relative[3];
+ unsigned char Absolute[3];
+ } subq;
+ unsigned char TrackChanged;
} cdrStruct;
extern cdrStruct cdr;
-void cdrDecodedBufferInterrupt();
-
void cdrReset();
+void cdrAttenuate(s16 *buf, int samples, int stereo);
+
void cdrInterrupt();
void cdrReadInterrupt();
+void cdrDecodedBufferInterrupt();
void cdrLidSeekInterrupt();
void cdrPlayInterrupt();
+void cdrDmaInterrupt();
+void LidInterrupt();
unsigned char cdrRead0(void);
unsigned char cdrRead1(void);
unsigned char cdrRead2(void);