X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fcdrom.c;h=cace6d90bd381c34280744e793fa71124cf05e4b;hb=ececcc61fa9115edcc51892a27aaa720d983e23e;hp=e01d7debd1e4b43f09a2510b13e423badb8f8b6b;hpb=8aeb66dcc917d0271e4574799b1793da7f3426c4;p=pcsx_rearmed.git diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index e01d7deb..cace6d90 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -89,8 +89,7 @@ static struct { boolean Play, Muted; int CurTrack; int Mode, File, Channel; - int Reset; - int NoErr; + unsigned char LocL[8]; int FirstSector; xa_decode_t Xa; @@ -208,6 +207,8 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; // so (PSXCLK / 75) = cdr read time (linuzappz) #define cdReadTime (PSXCLK / 75) +#define LOCL_INVALID 0xff + enum drive_state { DRIVESTATE_STANDBY = 0, // pause, play, read DRIVESTATE_LID_OPEN, @@ -243,8 +244,8 @@ static void sec2msf(unsigned int s, u8 *msf) { new_dyna_set_event(PSXINT_CDR, eCycle); \ } -// cdrPlaySeekReadInterrupt -#define CDRPLAYSEEKREAD_INT(eCycle, isFirst) { \ +// cdrPlayReadInterrupt +#define CDRPLAYREAD_INT(eCycle, isFirst) { \ u32 e_ = eCycle; \ psxRegs.interrupt |= (1 << PSXINT_CDREAD); \ if (isFirst) \ @@ -308,6 +309,8 @@ static void setIrq(int log_cmd) // (yes it's slow, but you probably don't want to modify it) void cdrLidSeekInterrupt(void) { + CDR_LOG_I("%u %s cdr.DriveState=%d\n", psxRegs.cycle, __func__, cdr.DriveState); + switch (cdr.DriveState) { default: case DRIVESTATE_STANDBY: @@ -369,10 +372,14 @@ void cdrLidSeekInterrupt(void) break; case DRIVESTATE_PREPARE_CD: - cdr.StatP |= STATUS_SEEK; - - cdr.DriveState = DRIVESTATE_STANDBY; - CDRLID_INT(cdReadTime * 26); + if (cdr.StatP & STATUS_SEEK) { + SetPlaySeekRead(cdr.StatP, 0); + cdr.DriveState = DRIVESTATE_STANDBY; + } + else { + SetPlaySeekRead(cdr.StatP, STATUS_SEEK); + CDRLID_INT(cdReadTime * 26); + } break; } } @@ -440,9 +447,10 @@ static void generate_subq(const u8 *time) cdr.subq.Absolute[2] = itob(time[2]); } -static void ReadTrack(const u8 *time) { +static int ReadTrack(const u8 *time) { unsigned char tmp[3]; struct SubQ *subq; + int read_ok; u16 crc; tmp[0] = itob(time[0]); @@ -450,15 +458,15 @@ static void ReadTrack(const u8 *time) { tmp[2] = itob(time[2]); if (memcmp(cdr.Prev, tmp, 3) == 0) - return; + return 1; CDR_LOG("ReadTrack *** %02x:%02x:%02x\n", tmp[0], tmp[1], tmp[2]); - cdr.NoErr = CDR_readTrack(tmp); + read_ok = CDR_readTrack(tmp); memcpy(cdr.Prev, tmp, 3); if (CheckSBI(time)) - return; + return read_ok; subq = (struct SubQ *)CDR_getBufferSub(); if (subq != NULL && cdr.CurTrack == 1) { @@ -482,6 +490,8 @@ static void ReadTrack(const u8 *time) { 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]); + + return read_ok; } static void cdrPlayInterrupt_Autopause() @@ -572,32 +582,13 @@ static void cdrReadInterrupt(void); static void cdrPrepCdda(s16 *buf, int samples); static void cdrAttenuate(s16 *buf, int samples, int stereo); -void cdrPlaySeekReadInterrupt(void) +void cdrPlayReadInterrupt(void) { if (cdr.Reading) { cdrReadInterrupt(); return; } - if (!cdr.Play && (cdr.StatP & STATUS_SEEK)) { - if (cdr.Stat) { - CDR_LOG_I("cdrom: seek stat hack\n"); - CDRPLAYSEEKREAD_INT(0x1000, 1); - return; - } - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - SetPlaySeekRead(cdr.StatP, 0); - cdr.Result[0] = cdr.StatP; - cdr.Stat = Complete; - setIrq(0x1002); - - Find_CurTrack(cdr.SetSectorPlay); - ReadTrack(cdr.SetSectorPlay); - cdr.TrackChanged = FALSE; - return; - } - if (!cdr.Play) return; CDR_LOG( "CDDA - %d:%d:%d\n", @@ -636,7 +627,7 @@ void cdrPlaySeekReadInterrupt(void) // update for CdlGetlocP/autopause generate_subq(cdr.SetSectorPlay); - CDRPLAYSEEKREAD_INT(cdReadTime, 0); + CDRPLAYREAD_INT(cdReadTime, 0); } #define CMD_PART2 0x100 @@ -647,8 +638,10 @@ void cdrInterrupt(void) { int error = 0; unsigned int seekTime = 0; u32 second_resp_time = 0; + const void *buf; u8 ParamC; u8 set_loc[3]; + int read_ok; u16 not_ready = 0; u16 Cmd; int i; @@ -687,9 +680,18 @@ void cdrInterrupt(void) { } switch (cdr.DriveState) { + case DRIVESTATE_PREPARE_CD: + if (Cmd > 2) { + // Syphon filter 2 expects commands to work shortly after it sees + // STATUS_ROTATING, so give up trying to emulate the startup seq + cdr.DriveState = DRIVESTATE_STANDBY; + cdr.StatP &= ~STATUS_SEEK; + psxRegs.interrupt &= ~(1 << PSXINT_CDRLID); + break; + } + // fallthrough case DRIVESTATE_LID_OPEN: case DRIVESTATE_RESCAN_CD: - case DRIVESTATE_PREPARE_CD: // no disk or busy with the initial scan, allowed cmds are limited not_ready = CMD_WHILE_NOT_READY; break; @@ -709,7 +711,7 @@ void cdrInterrupt(void) { // 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]); + CDR_LOG_I("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; } @@ -771,6 +773,7 @@ void cdrInterrupt(void) { */ Find_CurTrack(cdr.SetSectorPlay); ReadTrack(cdr.SetSectorPlay); + cdr.LocL[0] = LOCL_INVALID; cdr.TrackChanged = FALSE; cdr.FirstSector = 1; @@ -782,7 +785,7 @@ void cdrInterrupt(void) { // BIOS player - set flag again cdr.Play = TRUE; - CDRPLAYSEEKREAD_INT(cdReadTime + seekTime, 1); + CDRPLAYREAD_INT(cdReadTime + seekTime, 1); start_rotating = 1; break; @@ -830,6 +833,7 @@ void cdrInterrupt(void) { StopReading(); SetPlaySeekRead(cdr.StatP, 0); cdr.StatP &= ~STATUS_ROTATING; + cdr.LocL[0] = LOCL_INVALID; second_resp_time = 0x800; if (cdr.DriveState == DRIVESTATE_STANDBY) @@ -880,6 +884,7 @@ void cdrInterrupt(void) { StopCdda(); StopReading(); SetPlaySeekRead(cdr.StatP, 0); + cdr.LocL[0] = LOCL_INVALID; cdr.Muted = FALSE; cdr.Mode = 0x20; /* This fixes This is Football 2, Pooh's Party lockups */ second_resp_time = not_ready ? 70000 : 4100000; @@ -921,8 +926,12 @@ void cdrInterrupt(void) { break; case CdlGetlocL: + if (cdr.LocL[0] == LOCL_INVALID) { + error = 0x80; + goto set_error; + } SetResultSize(8); - memcpy(cdr.Result, cdr.Transfer, 8); + memcpy(cdr.Result, cdr.LocL, 8); break; case CdlGetlocP: @@ -973,7 +982,7 @@ void cdrInterrupt(void) { case CdlSeekP: StopCdda(); StopReading(); - SetPlaySeekRead(cdr.StatP, STATUS_SEEK); + SetPlaySeekRead(cdr.StatP, STATUS_SEEK | STATUS_ROTATING); seekTime = cdrSeekTime(cdr.SetSector); memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); @@ -990,10 +999,22 @@ void cdrInterrupt(void) { Rockman X5 = 0.5-4x - fix capcom logo */ - CDRPLAYSEEKREAD_INT(cdReadTime + seekTime, 1); + second_resp_time = cdReadTime + seekTime; start_rotating = 1; break; + case CdlSeekL + CMD_PART2: + case CdlSeekP + CMD_PART2: + SetPlaySeekRead(cdr.StatP, 0); + cdr.Stat = Complete; + + Find_CurTrack(cdr.SetSectorPlay); + read_ok = ReadTrack(cdr.SetSectorPlay); + if (read_ok && (buf = CDR_getBuffer())) + memcpy(cdr.LocL, buf, 8); + cdr.TrackChanged = FALSE; + break; + case CdlTest: case CdlTest + CMD_WHILE_NOT_READY: switch (cdr.Param[0]) { @@ -1058,6 +1079,7 @@ void cdrInterrupt(void) { case CdlReadToc: case CdlReadToc + CMD_WHILE_NOT_READY: + cdr.LocL[0] = LOCL_INVALID; second_resp_time = cdReadTime * 180 / 4; start_rotating = 1; break; @@ -1069,6 +1091,9 @@ void cdrInterrupt(void) { case CdlReadN: case CdlReadS: + if (cdr.Reading && !cdr.SetlocPending) + break; + Find_CurTrack(cdr.SetlocPending ? cdr.SetSector : cdr.SetSectorPlay); if ((cdr.Mode & MODE_CDDA) && cdr.CurTrack > 1) @@ -1087,20 +1112,21 @@ void cdrInterrupt(void) { // Fighting Force 2 - update subq time immediately // - fixes new game ReadTrack(cdr.SetSectorPlay); + cdr.LocL[0] = LOCL_INVALID; - CDRPLAYSEEKREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime) : cdReadTime * 2) + seekTime, 1); + CDRPLAYREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime) : cdReadTime * 2) + seekTime, 1); SetPlaySeekRead(cdr.StatP, STATUS_SEEK); start_rotating = 1; break; + case CdlSync: default: - CDR_LOG_I("Invalid command: %02x%s\n", - Cmd, not_ready ? " (not_ready)" : ""); error = ERROR_INVALIDCMD; // FALLTHROUGH set_error: + CDR_LOG_I("cdrom: cmd %02x error %02x\n", Cmd, error); SetResultSize(2); cdr.Result[0] = cdr.StatP | STATUS_ERROR; cdr.Result[1] = not_ready ? ERROR_NOTREADY : error; @@ -1109,7 +1135,6 @@ void cdrInterrupt(void) { } if (cdr.DriveState == DRIVESTATE_STOPPED && start_rotating) { - printf("cdr.DriveState %d->%d\n", cdr.DriveState, DRIVESTATE_STANDBY); cdr.DriveState = DRIVESTATE_STANDBY; cdr.StatP |= STATUS_ROTATING; } @@ -1215,21 +1240,23 @@ static void cdrUpdateTransferBuf(const u8 *buf) static void cdrReadInterrupt(void) { u8 *buf = NULL, *hdr; + int read_ok; SetPlaySeekRead(cdr.StatP, STATUS_READ | STATUS_ROTATING); - ReadTrack(cdr.SetSectorPlay); - if (cdr.NoErr) + read_ok = ReadTrack(cdr.SetSectorPlay); + if (read_ok) buf = CDR_getBuffer(); if (buf == NULL) - cdr.NoErr = 0; + read_ok = 0; - if (!cdr.NoErr) { + if (!read_ok) { CDR_LOG_I("cdrReadInterrupt() Log: err\n"); memset(cdr.Transfer, 0, DATA_SIZE); cdrReadInterruptSetResult(cdr.StatP | STATUS_ERROR); return; } + memcpy(cdr.LocL, buf, 8); if (!cdr.Irq1Pending) cdrUpdateTransferBuf(buf); @@ -1282,7 +1309,7 @@ static void cdrReadInterrupt(void) ReadTrack(cdr.SetSectorPlay); } - CDRPLAYSEEKREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime, 0); + CDRPLAYREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime, 0); } /* @@ -1564,9 +1591,15 @@ void cdrReset() { cdr.Channel = 1; cdr.Reg2 = 0x1f; cdr.Stat = NoIntr; - cdr.DriveState = DRIVESTATE_STANDBY; - cdr.StatP = STATUS_ROTATING; cdr.FifoOffset = DATA_SIZE; // fifo empty + 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; @@ -1615,7 +1648,7 @@ int cdrFreeze(void *f, int Mode) { if (!Config.Cdda) CDR_play(cdr.SetSectorPlay); if (psxRegs.interrupt & (1 << PSXINT_CDRPLAY_OLD)) - CDRPLAYSEEKREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime, 1); + CDRPLAYREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime, 1); } if ((cdr.freeze_ver & 0xffffff00) != 0x63647200) {