} subq;
unsigned char TrackChanged;
unsigned char ReportDelay;
- unsigned char unused3;
+ unsigned char PhysCdPropagations;
unsigned short sectorsRead;
unsigned int freeze_ver;
// 02, 12, 10
if (!(cdr.StatP & STATUS_SHELLOPEN)) {
+ StopReading();
SetPlaySeekRead(cdr.StatP, 0);
cdr.StatP |= STATUS_SHELLOPEN;
// IIRC this sometimes doesn't happen on real hw
// (when lots of commands are sent?)
- if (cdr.Reading) {
- StopReading();
- SetResultSize(2);
- cdr.Result[0] = cdr.StatP | STATUS_SEEKERROR;
- cdr.Result[1] = ERROR_SHELLOPEN;
- setIrq(DiskError, 0x1006);
- }
+ SetResultSize(2);
+ cdr.Result[0] = cdr.StatP | STATUS_SEEKERROR;
+ cdr.Result[1] = ERROR_SHELLOPEN;
if (cdr.CmdInProgress) {
psxRegs.interrupt &= ~(1 << PSXINT_CDR);
cdr.CmdInProgress = 0;
- SetResultSize(2);
cdr.Result[0] = cdr.StatP | STATUS_ERROR;
cdr.Result[1] = ERROR_NOTREADY;
- setIrq(DiskError, 0x1007);
}
+ setIrq(DiskError, 0x1006);
set_event(PSXINT_CDRLID, cdReadTime * 30);
break;
void cdrPlayReadInterrupt(void)
{
+ int hit = CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
+ if (!hit && cdr.PhysCdPropagations++ < 222) {
+ // this propagates real cdrom delays to the emulated game
+ CDRPLAYREAD_INT(cdReadTime / 2, 0);
+ return;
+ }
+ cdr.PhysCdPropagations = 0;
+
cdr.LastReadSeekCycles = psxRegs.cycle;
if (cdr.Reading) {
}
msfiAdd(cdr.SetSectorPlay, 1);
+ CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
// update for CdlGetlocP/autopause
generate_subq(cdr.SetSectorPlay);
CDRPLAYREAD_INT(cdReadTime, 0);
}
+static void softReset(void)
+{
+ CDR_getStatus(&stat);
+ if (stat.Status & STATUS_SHELLOPEN) {
+ cdr.DriveState = DRIVESTATE_LID_OPEN;
+ cdr.StatP = STATUS_SHELLOPEN;
+ }
+ else if (CdromId[0] == '\0') {
+ cdr.DriveState = DRIVESTATE_STOPPED;
+ cdr.StatP = 0;
+ }
+ else {
+ cdr.DriveState = DRIVESTATE_STANDBY;
+ cdr.StatP = STATUS_ROTATING;
+ }
+
+ cdr.FifoOffset = DATA_SIZE; // fifo empty
+ cdr.LocL[0] = LOCL_INVALID;
+ cdr.Mode = MODE_SIZE_2340;
+ cdr.Muted = FALSE;
+ SPU_setCDvol(cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight,
+ cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight, psxRegs.cycle);
+}
+
#define CMD_PART2 0x100
#define CMD_WHILE_NOT_READY 0x200
int read_ok;
u16 not_ready = 0;
u8 IrqStat = Acknowledge;
+ u8 DriveStateOld;
u16 Cmd;
int i;
second_resp_time = (((cdr.Mode & MODE_SPEED) ? 1 : 2) * 1097107);
}
SetPlaySeekRead(cdr.StatP, 0);
+ DriveStateOld = cdr.DriveState;
cdr.DriveState = DRIVESTATE_PAUSED;
+ if (DriveStateOld == DRIVESTATE_SEEK) {
+ // According to Duckstation this fails, but the
+ // exact conditions and effects are not clear.
+ // Moto Racer World Tour seems to rely on this.
+ // For now assume pause works anyway, just errors out.
+ error = ERROR_NOTREADY;
+ goto set_error;
+ }
break;
case CdlPause + CMD_PART2:
case CdlReset:
case CdlReset + CMD_WHILE_NOT_READY:
+ // note: nocash and Duckstation calls this 'Init', but
+ // the official SDK calls it 'Reset', and so do we
StopCdda();
StopReading();
- SetPlaySeekRead(cdr.StatP, 0);
- cdr.LocL[0] = LOCL_INVALID;
- cdr.Mode = MODE_SIZE_2340; /* This fixes This is Football 2, Pooh's Party lockups */
- cdr.DriveState = DRIVESTATE_PAUSED;
- cdr.Muted = FALSE;
- SPU_setCDvol(cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight,
- cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight, psxRegs.cycle);
+ softReset();
second_resp_time = not_ready ? 70000 : 4100000;
start_rotating = 1;
break;
seekTime = cdrSeekTime(cdr.SetSector);
memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
cdr.DriveState = DRIVESTATE_SEEK;
+ CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1],
+ cdr.SetSectorPlay[2]);
/*
Crusaders of Might and Magic = 0.5x-4x
- fix cutscene speech start
cdr.SubqForwardSectors = 1;
cdr.sectorsRead = 0;
cdr.DriveState = DRIVESTATE_SEEK;
+ CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1],
+ cdr.SetSectorPlay[2]);
cycles = (cdr.Mode & MODE_SPEED) ? cdReadTime : cdReadTime * 2;
cycles += seekTime;
cdrReadInterruptSetResult(cdr.StatP);
msfiAdd(cdr.SetSectorPlay, 1);
+ CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
CDRPLAYREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime, 0);
}
}
void cdrWrite0(unsigned char rt) {
- CDR_LOG_IO("cdr w0.idx: %02x\n", rt);
+ CDR_LOG_IO("cdr w0.x.idx: %02x\n", rt);
cdr.Ctrl = (rt & 3) | (cdr.Ctrl & ~3);
}
if (cdr.ResultP == cdr.ResultC)
cdr.ResultReady = 0;
- CDR_LOG_IO("cdr r1.rsp: %02x #%u\n", psxHu8(0x1801), cdr.ResultP - 1);
+ CDR_LOG_IO("cdr r1.x.rsp: %02x #%u\n", psxHu8(0x1801), cdr.ResultP - 1);
return psxHu8(0x1801);
}
void cdrWrite1(unsigned char rt) {
- const char *rnames[] = { "cmd", "smd", "smc", "arr" }; (void)rnames;
+ const char *rnames[] = { "0.cmd", "1.smd", "2.smc", "3.arr" }; (void)rnames;
CDR_LOG_IO("cdr w1.%s: %02x\n", rnames[cdr.Ctrl & 3], rt);
switch (cdr.Ctrl & 3) {
SysPrintf(" Param[%d] = {", cdr.ParamC);
for (i = 0; i < cdr.ParamC; i++)
SysPrintf(" %x,", cdr.Param[i]);
- SysPrintf("}\n");
- } else {
- SysPrintf("\n");
+ SysPrintf("}");
}
+ SysPrintf(" @%08x\n", psxRegs.pc);
#endif
cdr.ResultReady = 0;
else
CDR_LOG_I("read empty fifo (%d)\n", cdr.FifoSize);
- CDR_LOG_IO("cdr r2.dat: %02x\n", ret);
+ CDR_LOG_IO("cdr r2.x.dat: %02x\n", ret);
return ret;
}
void cdrWrite2(unsigned char rt) {
- const char *rnames[] = { "prm", "ien", "all", "arl" }; (void)rnames;
+ const char *rnames[] = { "0.prm", "1.ien", "2.all", "3.arl" }; (void)rnames;
CDR_LOG_IO("cdr w2.%s: %02x\n", rnames[cdr.Ctrl & 3], rt);
switch (cdr.Ctrl & 3) {
else
psxHu8(0x1803) = cdr.IrqMask | 0xE0;
- CDR_LOG_IO("cdr r3.%s: %02x\n", (cdr.Ctrl & 1) ? "ifl" : "ien", psxHu8(0x1803));
+ CDR_LOG_IO("cdr r3.%d.%s: %02x\n", cdr.Ctrl & 3,
+ (cdr.Ctrl & 1) ? "ifl" : "ien", psxHu8(0x1803));
return psxHu8(0x1803);
}
void cdrWrite3(unsigned char rt) {
- const char *rnames[] = { "req", "ifl", "alr", "ava" }; (void)rnames;
+ const char *rnames[] = { "0.req", "1.ifl", "2.alr", "3.ava" }; (void)rnames;
u8 ll, lr, rl, rr;
CDR_LOG_IO("cdr w3.%s: %02x\n", rnames[cdr.Ctrl & 3], rt);
rl == cdr.AttenuatorRightToLeft &&
rr == cdr.AttenuatorRightToRight)
return;
- cdr.AttenuatorLeftToLeftT = ll; cdr.AttenuatorLeftToRightT = lr;
- cdr.AttenuatorRightToLeftT = rl; cdr.AttenuatorRightToRightT = rr;
+ cdr.AttenuatorLeftToLeft = ll; cdr.AttenuatorLeftToRight = lr;
+ cdr.AttenuatorRightToLeft = rl; cdr.AttenuatorRightToRight = rr;
CDR_LOG_I("CD-XA Volume: %02x %02x | %02x %02x\n", ll, lr, rl, rr);
SPU_setCDvol(ll, lr, rl, rr, psxRegs.cycle);
}
switch (chcr & 0x71000000) {
case 0x11000000:
+ madr &= ~3;
ptr = getDmaRam(madr, &max_words);
if (ptr == INVALID_PTR) {
CDR_LOG_I("psxDma3() Log: *** DMA 3 *** NULL Pointer!\n");
cdr.FilterChannel = 0;
cdr.IrqMask = 0x1f;
cdr.IrqStat = NoIntr;
- cdr.FifoOffset = DATA_SIZE; // fifo empty
- CDR_getStatus(&stat);
- if (stat.Status & STATUS_SHELLOPEN) {
- cdr.DriveState = DRIVESTATE_LID_OPEN;
- cdr.StatP = STATUS_SHELLOPEN;
- }
- else if (CdromId[0] == '\0') {
- cdr.DriveState = DRIVESTATE_STOPPED;
- cdr.StatP = 0;
- }
- else {
- cdr.DriveState = DRIVESTATE_STANDBY;
- cdr.StatP = STATUS_ROTATING;
- }
-
// BIOS player - default values
cdr.AttenuatorLeftToLeft = 0x80;
cdr.AttenuatorLeftToRight = 0x00;
cdr.AttenuatorRightToLeft = 0x00;
cdr.AttenuatorRightToRight = 0x80;
- SPU_setCDvol(cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight,
- cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight, psxRegs.cycle);
+ softReset();
getCdInfo();
}