X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fcdrom.c;h=12945d60cfbc3fe0b3c452cf1132478e3fb57368;hb=4134c627c94686ef483a400e7664decf10c64e1e;hp=42f13af219e877c843644638e42434c1dfc90972;hpb=70c1043e63dafcf92b0f4dc0932326a6d042fbb4;p=pcsx_rearmed.git diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 42f13af2..12945d60 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -463,7 +463,8 @@ static int ReadTrack(const u8 *time) { CDR_LOG("ReadTrack *** %02x:%02x:%02x\n", tmp[0], tmp[1], tmp[2]); read_ok = CDR_readTrack(tmp); - memcpy(cdr.Prev, tmp, 3); + if (read_ok) + memcpy(cdr.Prev, tmp, 3); if (CheckSBI(time)) return read_ok; @@ -577,6 +578,27 @@ static int cdrSeekTime(unsigned char *target) return seekTime; } +static u32 cdrAlignTimingHack(u32 cycles) +{ + /* + * timing hack for T'ai Fu - Wrath of the Tiger: + * The game has a bug where it issues some cdc commands from a low priority + * vint handler, however there is a higher priority default bios handler + * that acks the vint irq and returns, so game's handler is not reached + * (see bios irq handler chains at e004 and the game's irq handling func + * at 80036810). For the game to work, vint has to arrive after the bios + * vint handler rejects some other irq (of which only cd and rcnt2 are + * active), but before the game's handler loop reads I_STAT. The time + * window for this is quite small (~1k cycles of so). Apparently this + * somehow happens naturally on the real hardware. + */ + u32 vint_rel = rcnts[3].cycleStart + 63000 - psxRegs.cycle; + vint_rel += PSXCLK / 60; + while ((s32)(vint_rel - cycles) < 0) + vint_rel += PSXCLK / 60; + return vint_rel; +} + static void cdrUpdateTransferBuf(const u8 *buf); static void cdrReadInterrupt(void); static void cdrPrepCdda(s16 *buf, int samples); @@ -636,7 +658,7 @@ void cdrPlayReadInterrupt(void) void cdrInterrupt(void) { int start_rotating = 0; int error = 0; - unsigned int seekTime = 0; + u32 cycles, seekTime = 0; u32 second_resp_time = 0; const void *buf; u8 ParamC; @@ -711,7 +733,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; } @@ -1006,6 +1028,7 @@ void cdrInterrupt(void) { case CdlSeekL + CMD_PART2: case CdlSeekP + CMD_PART2: SetPlaySeekRead(cdr.StatP, 0); + cdr.Result[0] = cdr.StatP; cdr.Stat = Complete; Find_CurTrack(cdr.SetSectorPlay); @@ -1091,6 +1114,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) @@ -1111,7 +1137,10 @@ void cdrInterrupt(void) { ReadTrack(cdr.SetSectorPlay); cdr.LocL[0] = LOCL_INVALID; - CDRPLAYREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime) : cdReadTime * 2) + seekTime, 1); + cycles = (cdr.Mode & 0x80) ? cdReadTime : cdReadTime * 2; + cycles += seekTime; + cycles = cdrAlignTimingHack(cycles); + CDRPLAYREAD_INT(cycles, 1); SetPlaySeekRead(cdr.StatP, STATUS_SEEK); start_rotating = 1; @@ -1249,7 +1278,6 @@ static void cdrReadInterrupt(void) if (!read_ok) { CDR_LOG_I("cdrReadInterrupt() Log: err\n"); - memset(cdr.Transfer, 0, DATA_SIZE); cdrReadInterruptSetResult(cdr.StatP | STATUS_ERROR); return; } @@ -1514,7 +1542,7 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { switch (chcr & 0x71000000) { case 0x11000000: ptr = (u8 *)PSXM(madr); - if (ptr == NULL) { + if (ptr == INVALID_PTR) { CDR_LOG_I("psxDma3() Log: *** DMA 3 *** NULL Pointer!\n"); break; }