X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fcdrom.c;h=7a25c57dab25d714b53b2585baace3b5eb523e34;hb=2e88c3173da3048d8502f4ab0ee70fe215f549eb;hp=6f0b92cead6a59bd8972f3153230ddc605cde8a2;hpb=73817437ddebaf6d53a401d723d4c8f6971829a7;p=pcsx_rearmed.git diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 6f0b92ce..7a25c57d 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -49,7 +49,7 @@ static unsigned char *pTransfer; static s16 read_buf[CD_FRAMESIZE_RAW/2]; /* CD-ROM magic numbers */ -#define CdlSync 0 /* nocash documentation : "Uh, actually, returns error code 40h = Invalid Command...?" */ +#define CdlSync 0 /* nocash documentation : "Uh, actually, returns error code 40h = Invalid Command...?" */ #define CdlNop 1 #define CdlSetloc 2 #define CdlPlay 3 @@ -84,12 +84,12 @@ static s16 read_buf[CD_FRAMESIZE_RAW/2]; char *CmdName[0x100]= { "CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", "CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", - "CdlStop", "CdlPause", "CdlReset", "CdlMute", + "CdlStop", "CdlPause", "CdlReset", "CdlMute", "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetparam", "CdlGetlocL", "CdlGetlocP", "CdlReadT", "CdlGetTN", "CdlGetTD", "CdlSeekL", "CdlSeekP", "CdlSetclock", "CdlGetclock", "CdlTest", "CdlID", "CdlReadS", - "CdlInit", NULL, "CDlReadToc", NULL + "CdlInit", NULL, "CDlReadToc", NULL }; unsigned char Test04[] = { 0 }; @@ -451,7 +451,6 @@ static void cdrPlayInterrupt_Autopause() 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; @@ -527,13 +526,14 @@ void cdrPlayInterrupt() 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); @@ -570,6 +570,8 @@ void cdrInterrupt() { int error = 0; int delay; unsigned int seekTime = 0; + u8 set_loc[3]; + int i; // Reschedule IRQ if (cdr.Stat) { @@ -603,6 +605,31 @@ void cdrInterrupt() { 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: @@ -612,7 +639,7 @@ void cdrInterrupt() { // XXX: wrong, should seek instead.. cdr.Seeked = SEEK_DONE; } - + cdr.FastBackward = 0; cdr.FastForward = 0; @@ -659,8 +686,9 @@ void cdrInterrupt() { ReadTrack(cdr.SetSectorPlay); cdr.TrackChanged = FALSE; + StopReading(); if (!Config.Cdda) - CDR_play(); + CDR_play(cdr.SetSectorPlay); // Vib Ribbon: gameplay checks flag cdr.StatP &= ~STATUS_SEEK; @@ -678,6 +706,7 @@ void cdrInterrupt() { case CdlForward: // TODO: error 80 if stopped cdr.Stat = Complete; + // GameShark CD Player: Calls 2x + Play 2x cdr.FastForward = 1; cdr.FastBackward = 0; @@ -687,7 +716,7 @@ void cdrInterrupt() { cdr.Stat = Complete; // GameShark CD Player: Calls 2x + Play 2x - cdr.FastBackward =1; + cdr.FastBackward = 1; cdr.FastForward = 0; break; @@ -735,8 +764,10 @@ void cdrInterrupt() { /* Gundam Battle Assault 2: much slower (*) - Fixes boot, gameplay + Hokuto no Ken 2: slower - Fixes intro + subtitles + InuYasha - Feudal Fairy Tale: slower - Fixes battles */ @@ -744,10 +775,8 @@ void cdrInterrupt() { * The timings from Duckstation are based upon hardware tests. * 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. - * - * We will need to get around this for Bedlam/Rise 2 later... * */ - if (cdr.DriveState != DRIVESTATE_STANDBY) + if (cdr.DriveState == DRIVESTATE_STANDBY) { delay = 7000; } @@ -768,7 +797,7 @@ void cdrInterrupt() { case CdlReset: cdr.Muted = FALSE; - cdr.Mode = 0x20; /* Needed for This is Football 2, Pooh's Party and possibly others. */ + cdr.Mode = 0x20; /* This fixes This is Football 2, Pooh's Party lockups */ AddIrqQueue(CdlReset + 0x100, 4100000); no_busy_error = 1; start_rotating = 1; @@ -796,6 +825,7 @@ void cdrInterrupt() { break; case CdlGetparam: + /* Gameblabla : According to mednafen, Result size should be 5 and done this way. */ SetResultSize(5); cdr.Result[1] = cdr.Mode; cdr.Result[2] = 0; @@ -812,9 +842,6 @@ void cdrInterrupt() { case CdlGetlocP: SetResultSize(8); memcpy(&cdr.Result, &cdr.subq, 8); - - if (!cdr.Play && !cdr.Reading) - cdr.Result[1] = 0; // HACK? break; case CdlReadT: // SetSession? @@ -1001,7 +1028,7 @@ void cdrInterrupt() { - fixes cutscenes C-12 - Final Resistance - doesn't like seek */ - + /* By nicolasnoble from PCSX Redux : "It LOOKS like this logic is wrong, therefore disabling it with `&& false` for now. @@ -1011,6 +1038,7 @@ void cdrInterrupt() { tries to protect itself against errors by preventing from issuing a GetLocP while it knows the last status was "seek". But this makes the logic just softlock as it'll never get a notification about the fact the drive is done seeking and the read actually started. + In other words, this state machine here is probably wrong in assuming the response to ReadS/ReadN is done right away. It's rather when it's done seeking, and the read has actually started. This probably requires a bit more work to make sure seek delays are processed properly. @@ -1021,12 +1049,12 @@ void cdrInterrupt() { */ cdr.StatP |= STATUS_READ; cdr.StatP &= ~STATUS_SEEK; + CDREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime) : cdReadTime * 2) + seekTime); cdr.Result[0] = cdr.StatP; start_rotating = 1; break; - case CdlSync: default: CDR_LOG_I("Invalid command: %02x\n", Irq); @@ -1148,7 +1176,7 @@ void cdrReadInterrupt() { if (buf == NULL) cdr.NoErr = 0; - if (cdr.NoErr == 0) { + if (!cdr.NoErr) { CDR_LOG_I("cdrReadInterrupt() Log: err\n"); memset(cdr.Transfer, 0, DATA_SIZE); cdr.Stat = DiskError; @@ -1181,6 +1209,19 @@ void cdrReadInterrupt() { 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; } @@ -1274,9 +1315,6 @@ unsigned char cdrRead1(void) { } void cdrWrite1(unsigned char rt) { - u8 set_loc[3]; - int i; - CDR_LOG_IO("cdr w1: %02x\n", rt); switch (cdr.Ctrl & 3) { @@ -1310,31 +1348,6 @@ void cdrWrite1(unsigned char rt) { 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: @@ -1483,7 +1496,7 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { ptr = (u8 *)PSXM(madr); - if (ptr == NULL) { + if (ptr == INVALID_PTR) { CDR_LOG("psxDma3() Log: *** DMA 3 *** NULL Pointer!\n"); break; } @@ -1556,9 +1569,7 @@ void cdrReset() { cdr.DriveState = DRIVESTATE_STANDBY; cdr.StatP = STATUS_ROTATING; pTransfer = cdr.Transfer; - cdr.SetlocPending = 0; - cdr.m_locationChanged = FALSE; - + // BIOS player - default values cdr.AttenuatorLeftToLeft = 0x80; cdr.AttenuatorLeftToRight = 0x00; @@ -1603,7 +1614,7 @@ int cdrFreeze(void *f, int Mode) { Find_CurTrack(cdr.SetSectorPlay); if (!Config.Cdda) - CDR_play(); + CDR_play(cdr.SetSectorPlay); } if ((cdr.freeze_ver & 0xffffff00) != 0x63647200) {