#endif
//#define CDR_LOG_CMD_IRQ
-cdrStruct cdr;
+static struct {
+ unsigned char OCUP;
+ unsigned char Reg1Mode;
+ unsigned char Reg2;
+ unsigned char CmdProcess;
+ unsigned char Ctrl;
+ unsigned char Stat;
+
+ unsigned char StatP;
+
+ unsigned char Transfer[DATA_SIZE];
+ struct {
+ unsigned char Track;
+ unsigned char Index;
+ unsigned char Relative[3];
+ unsigned char Absolute[3];
+ } subq;
+ unsigned char TrackChanged;
+ boolean m_locationChanged;
+ unsigned char pad1[2];
+ unsigned int freeze_ver;
+
+ unsigned char Prev[4];
+ unsigned char Param[8];
+ unsigned char Result[16];
+
+ unsigned char ParamC;
+ unsigned char ParamP;
+ unsigned char ResultC;
+ unsigned char ResultP;
+ unsigned char ResultReady;
+ unsigned char Cmd;
+ unsigned char Readed;
+ unsigned char SetlocPending;
+ u32 Reading;
+
+ unsigned char ResultTN[6];
+ unsigned char ResultTD[4];
+ unsigned char SetSectorPlay[4];
+ unsigned char SetSectorEnd[4];
+ unsigned char SetSector[4];
+ unsigned char Track;
+ boolean Play, Muted;
+ int CurTrack;
+ int Mode, File, Channel;
+ int Reset;
+ int NoErr;
+ int FirstSector;
+
+ xa_decode_t Xa;
+
+ int Init;
+
+ u16 Irq;
+ u8 IrqRepeated;
+ u32 eCycle;
+
+ u8 Seeked;
+
+ u8 DriveState;
+ u8 FastForward;
+ u8 FastBackward;
+ u8 pad;
+
+ u8 AttenuatorLeftToLeft, AttenuatorLeftToRight;
+ u8 AttenuatorRightToRight, AttenuatorRightToLeft;
+ u8 AttenuatorLeftToLeftT, AttenuatorLeftToRightT;
+ u8 AttenuatorRightToRightT, AttenuatorRightToLeftT;
+} cdr;
static unsigned char *pTransfer;
static s16 read_buf[CD_FRAMESIZE_RAW/2];
#define CdlGetQ 29
#define CdlReadToc 30
-char *CmdName[0x100]= {
+#ifdef CDR_LOG_CMD_IRQ
+static const char * const CmdName[0x100] = {
"CdlSync", "CdlNop", "CdlSetloc", "CdlPlay",
"CdlForward", "CdlBackward", "CdlReadN", "CdlStandby",
"CdlStop", "CdlPause", "CdlReset", "CdlMute",
"CdlGetclock", "CdlTest", "CdlID", "CdlReadS",
"CdlInit", NULL, "CDlReadToc", NULL
};
+#endif
unsigned char Test04[] = { 0 };
unsigned char Test05[] = { 0 };
cdr.ResultReady = 1; \
}
-static void setIrq(void)
+static void setIrq(int log_cmd)
{
if (cdr.Stat & cdr.Reg2)
psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+
+#ifdef CDR_LOG_CMD_IRQ
+ {
+ int i;
+ SysPrintf("CDR IRQ=%d cmd %02x stat %02x: ",
+ !!(cdr.Stat & cdr.Reg2), log_cmd, cdr.Stat);
+ for (i = 0; i < cdr.ResultC; i++)
+ SysPrintf("%02x ", cdr.Result[i]);
+ SysPrintf("\n");
+ }
+#endif
}
// timing used in this function was taken from tests on real hardware
//cdr.ResultReady = 1;
//cdr.Stat = DataReady;
cdr.Stat = DataEnd;
- setIrq();
+ setIrq(0x200);
StopCdda();
}
else if (((cdr.Mode & MODE_REPORT) || cdr.FastForward || cdr.FastBackward)) {
- CDR_readCDDA(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], (u8 *)read_buf);
cdr.Result[0] = cdr.StatP;
cdr.Result[1] = cdr.subq.Track;
cdr.Result[2] = cdr.subq.Index;
cdr.Stat = DataReady;
SetResultSize(8);
- setIrq();
+ setIrq(0x201);
}
}
cdr.Seeked = SEEK_DONE;
if (cdr.Irq == 0) {
cdr.Stat = Complete;
- setIrq();
+ setIrq(0x202);
}
if (cdr.SetlocPending) {
StopCdda();
cdr.TrackChanged = TRUE;
}
+ else {
+ CDR_readCDDA(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], (u8 *)read_buf);
+ }
if (!cdr.Irq && !cdr.Stat && (cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT)))
cdrPlayInterrupt_Autopause();
- if (!cdr.Play) return;
-
- if (CDR_readCDDA && !cdr.Muted && cdr.Mode & MODE_REPORT) {
+ if (CDR_readCDDA && !cdr.Muted && !Config.Cdda) {
cdrAttenuate(read_buf, CD_FRAMESIZE_RAW / 4, 1);
if (SPU_playCDDAchannel)
SPU_playCDDAchannel(read_buf, CD_FRAMESIZE_RAW);
int error = 0;
int delay;
unsigned int seekTime = 0;
+ u8 set_loc[3];
+ int i;
// Reschedule IRQ
if (cdr.Stat) {
break;
case CdlSetloc:
+ CDR_LOG("CDROM setloc command (%02X, %02X, %02X)\n", cdr.Param[0], cdr.Param[1], cdr.Param[2]);
+
+ // MM must be BCD, SS must be BCD and <0x60, FF must be BCD and <0x75
+ if (((cdr.Param[0] & 0x0F) > 0x09) || (cdr.Param[0] > 0x99) || ((cdr.Param[1] & 0x0F) > 0x09) || (cdr.Param[1] >= 0x60) || ((cdr.Param[2] & 0x0F) > 0x09) || (cdr.Param[2] >= 0x75))
+ {
+ CDR_LOG("Invalid/out of range seek to %02X:%02X:%02X\n", cdr.Param[0], cdr.Param[1], cdr.Param[2]);
+ error = ERROR_INVALIDARG;
+ goto set_error;
+ }
+ else
+ {
+ for (i = 0; i < 3; i++)
+ {
+ set_loc[i] = btoi(cdr.Param[i]);
+ }
+
+ i = msf2sec(cdr.SetSectorPlay);
+ i = abs(i - msf2sec(set_loc));
+ if (i > 16)
+ cdr.Seeked = SEEK_PENDING;
+
+ memcpy(cdr.SetSector, set_loc, 3);
+ cdr.SetSector[3] = 0;
+ cdr.SetlocPending = 1;
+ }
break;
do_CdlPlay:
ReadTrack(cdr.SetSectorPlay);
cdr.TrackChanged = FALSE;
+ StopReading();
if (!Config.Cdda)
CDR_play(cdr.SetSectorPlay);
* Mednafen's timing don't work for Gundam Battle Assault 2 in PAL/50hz mode,
* seems to be timing sensitive as it can depend on the CPU's clock speed.
* */
- if (cdr.DriveState != DRIVESTATE_STANDBY)
+ if (cdr.DriveState == DRIVESTATE_STANDBY)
{
delay = 7000;
}
case CdlGetlocP:
SetResultSize(8);
memcpy(&cdr.Result, &cdr.subq, 8);
-
- if (!cdr.Play && !cdr.Reading)
- cdr.Result[1] = 0; // HACK?
break;
case CdlReadT: // SetSession?
*/
CDRMISC_INT(cdr.Seeked == SEEK_DONE ? 0x800 : cdReadTime * 4);
cdr.Seeked = SEEK_PENDING;
+ memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
start_rotating = 1;
break;
}
finish:
- setIrq();
+ setIrq(Irq);
cdr.ParamC = 0;
-
-#ifdef CDR_LOG_CMD_IRQ
- {
- int i;
- SysPrintf("CDR IRQ %d cmd %02x stat %02x: ",
- !!(cdr.Stat & cdr.Reg2), Irq, cdr.Stat);
- for (i = 0; i < cdr.ResultC; i++)
- SysPrintf("%02x ", cdr.Result[i]);
- SysPrintf("\n");
- }
-#endif
}
#ifdef HAVE_ARMV7
int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector);
if (!ret) {
cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo);
+ /*
+ * Gameblabla -
+ * This is a hack for Megaman X4, Castlevania etc...
+ * that regressed from the new m_locationChanged and CDROM timings changes.
+ * It is mostly noticeable in Castevania however and the stuttering can be very jarring.
+ *
+ * According to PCSX redux authors, we shouldn't cause a location change if
+ * the sector difference is too small.
+ * I attempted to go with that approach but came empty handed.
+ * So for now, let's just set cdr.m_locationChanged to false when playing back any ADPCM samples.
+ * This does not regress Crash Team Racing's intro at least.
+ */
+ cdr.m_locationChanged = FALSE;
SPU_playADPCMchannel(&cdr.Xa);
cdr.FirstSector = 0;
}
if (!(cdr.Mode & MODE_STRSND) || !(cdr.Transfer[4+2] & 0x4)) {
cdr.Stat = DataReady;
- setIrq();
+ setIrq(0x203);
}
// update for CdlGetlocP
// What means the 0x10 and the 0x08 bits? I only saw it used by the bios
cdr.Ctrl |= 0x18;
- CDR_LOG_IO("cdr r0: %02x\n", cdr.Ctrl);
+ CDR_LOG_IO("cdr r0.sta: %02x\n", cdr.Ctrl);
return psxHu8(0x1800) = cdr.Ctrl;
}
void cdrWrite0(unsigned char rt) {
- CDR_LOG_IO("cdr w0: %02x\n", rt);
+ CDR_LOG_IO("cdr w0.idx: %02x\n", rt);
cdr.Ctrl = (rt & 3) | (cdr.Ctrl & ~3);
}
if (cdr.ResultP == cdr.ResultC)
cdr.ResultReady = 0;
- CDR_LOG_IO("cdr r1: %02x\n", psxHu8(0x1801));
+ CDR_LOG_IO("cdr r1.rsp: %02x #%u\n", psxHu8(0x1801), cdr.ResultP - 1);
return psxHu8(0x1801);
}
void cdrWrite1(unsigned char rt) {
- u8 set_loc[3];
- int i;
-
- CDR_LOG_IO("cdr w1: %02x\n", rt);
+ const char *rnames[] = { "cmd", "smd", "smc", "arr" }; (void)rnames;
+ CDR_LOG_IO("cdr w1.%s: %02x\n", rnames[cdr.Ctrl & 3], rt);
switch (cdr.Ctrl & 3) {
case 0:
#ifdef CDR_LOG_CMD_IRQ
SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]);
if (cdr.ParamC) {
+ int i;
SysPrintf(" Param[%d] = {", cdr.ParamC);
for (i = 0; i < cdr.ParamC; i++)
SysPrintf(" %x,", cdr.Param[i]);
AddIrqQueue(cdr.Cmd, 0x800);
switch (cdr.Cmd) {
- case CdlSetloc:
- CDR_LOG("CDROM setloc command (%02X, %02X, %02X)\n", cdr.Param[0], cdr.Param[1], cdr.Param[2]);
-
- // MM must be BCD, SS must be BCD and <0x60, FF must be BCD and <0x75
- if (((cdr.Param[0] & 0x0F) > 0x09) || (cdr.Param[0] > 0x99) || ((cdr.Param[1] & 0x0F) > 0x09) || (cdr.Param[1] >= 0x60) || ((cdr.Param[2] & 0x0F) > 0x09) || (cdr.Param[2] >= 0x75))
- {
- CDR_LOG("Invalid/out of range seek to %02X:%02X:%02X\n", cdr.Param[0], cdr.Param[1], cdr.Param[2]);
- }
- else
- {
- for (i = 0; i < 3; i++)
- {
- set_loc[i] = btoi(cdr.Param[i]);
- }
-
- i = msf2sec(cdr.SetSectorPlay);
- i = abs(i - msf2sec(set_loc));
- if (i > 16)
- cdr.Seeked = SEEK_PENDING;
-
- memcpy(cdr.SetSector, set_loc, 3);
- cdr.SetSector[3] = 0;
- cdr.SetlocPending = 1;
- }
- break;
case CdlReadN:
case CdlReadS:
ret = *pTransfer++;
}
- CDR_LOG_IO("cdr r2: %02x\n", ret);
+ CDR_LOG_IO("cdr r2.dat: %02x\n", ret);
return ret;
}
void cdrWrite2(unsigned char rt) {
- CDR_LOG_IO("cdr w2: %02x\n", rt);
+ const char *rnames[] = { "prm", "ien", "all", "arl" }; (void)rnames;
+ CDR_LOG_IO("cdr w2.%s: %02x\n", rnames[cdr.Ctrl & 3], rt);
switch (cdr.Ctrl & 3) {
case 0:
return;
case 1:
cdr.Reg2 = rt;
- setIrq();
+ setIrq(0x204);
return;
case 2:
cdr.AttenuatorLeftToLeftT = rt;
else
psxHu8(0x1803) = cdr.Reg2 | 0xE0;
- CDR_LOG_IO("cdr r3: %02x\n", psxHu8(0x1803));
+ CDR_LOG_IO("cdr r3.%s: %02x\n", (cdr.Ctrl & 1) ? "ifl" : "ien", psxHu8(0x1803));
return psxHu8(0x1803);
}
void cdrWrite3(unsigned char rt) {
- CDR_LOG_IO("cdr w3: %02x\n", rt);
+ const char *rnames[] = { "req", "ifl", "alr", "ava" }; (void)rnames;
+ CDR_LOG_IO("cdr w3.%s: %02x\n", rnames[cdr.Ctrl & 3], rt);
switch (cdr.Ctrl & 3) {
case 0: