X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=libpcsxcore%2Fcdrom.c;h=2d9d77f0a0012d0688631c271732441f81eeab88;hp=7b5cdf2ce065bd3a962814a7f688e02362e0aeca;hb=e3d555e0f3578b4e317f9739a715744cbe1a8395;hpb=55b8460a0e10da33133a98faeeb5b2375ef91dc0 diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 7b5cdf2c..2d9d77f0 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -24,6 +24,7 @@ #include "cdrom.h" #include "ppf.h" #include "psxdma.h" +#include "arm_features.h" /* logging */ #if 0 @@ -47,7 +48,7 @@ cdrStruct cdr; static unsigned char *pTransfer; /* CD-ROM magic numbers */ -#define CdlSync 0 +#define CdlSync 0 /* nocash documentation : "Uh, actually, returns error code 40h = Invalid Command...?" */ #define CdlNop 1 #define CdlSetloc 2 #define CdlPlay 3 @@ -57,12 +58,12 @@ static unsigned char *pTransfer; #define CdlStandby 7 #define CdlStop 8 #define CdlPause 9 -#define CdlInit 10 +#define CdlReset 10 #define CdlMute 11 #define CdlDemute 12 #define CdlSetfilter 13 #define CdlSetmode 14 -#define CdlGetmode 15 +#define CdlGetparam 15 #define CdlGetlocL 16 #define CdlGetlocP 17 #define CdlReadT 18 @@ -75,19 +76,19 @@ static unsigned char *pTransfer; #define CdlTest 25 #define CdlID 26 #define CdlReadS 27 -#define CdlReset 28 +#define CdlInit 28 #define CdlGetQ 29 #define CdlReadToc 30 char *CmdName[0x100]= { "CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", "CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", - "CdlStop", "CdlPause", "CdlInit", "CdlMute", - "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode", + "CdlStop", "CdlPause", "CdlReset", "CdlMute", + "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetparam", "CdlGetlocL", "CdlGetlocP", "CdlReadT", "CdlGetTN", "CdlGetTD", "CdlSeekL", "CdlSeekP", "CdlSetclock", "CdlGetclock", "CdlTest", "CdlID", "CdlReadS", - "CdlReset", NULL, "CDlReadToc", NULL + "CdlInit", NULL, "CDlReadToc", NULL }; unsigned char Test04[] = { 0 }; @@ -126,7 +127,7 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; #define STATUS_ERROR (1<<0) // 0x01 /* Errors */ -#define ERROR_NOT_READY (1<<7) // 0x80 +#define ERROR_NOTREADY (1<<7) // 0x80 #define ERROR_INVALIDCMD (1<<6) // 0x40 #define ERROR_INVALIDARG (1<<5) // 0x20 @@ -205,7 +206,7 @@ static void sec2msf(unsigned int s, u8 *msf) { cdr.Reading = 0; \ psxRegs.interrupt &= ~(1 << PSXINT_CDREAD); \ } \ - cdr.StatP &= ~STATUS_READ;\ + cdr.StatP &= ~(STATUS_READ|STATUS_SEEK);\ } #define StopCdda() { \ @@ -495,6 +496,7 @@ void cdrPlayInterrupt() if (cdr.SetlocPending) { memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); cdr.SetlocPending = 0; + cdr.m_locationChanged = TRUE; } Find_CurTrack(cdr.SetSectorPlay); ReadTrack(cdr.SetSectorPlay); @@ -526,7 +528,15 @@ void cdrPlayInterrupt() } } - CDRMISC_INT(cdReadTime); + if (cdr.m_locationChanged) + { + CDRMISC_INT(cdReadTime * 30); + cdr.m_locationChanged = FALSE; + } + else + { + CDRMISC_INT(cdReadTime); + } // update for CdlGetlocP/autopause generate_subq(cdr.SetSectorPlay); @@ -538,6 +548,7 @@ void cdrInterrupt() { int start_rotating = 0; int error = 0; int delay; + unsigned int seekTime = 0; // Reschedule IRQ if (cdr.Stat) { @@ -564,10 +575,6 @@ void cdrInterrupt() { cdr.Irq = 0; switch (Irq) { - case CdlSync: - // TOOD: sometimes/always return error? - break; - case CdlNop: if (cdr.DriveState != DRIVESTATE_LID_OPEN) cdr.StatP &= ~STATUS_SHELLOPEN; @@ -587,6 +594,7 @@ void cdrInterrupt() { if (cdr.SetlocPending) { memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); cdr.SetlocPending = 0; + cdr.m_locationChanged = TRUE; } // BIOS CD Player @@ -714,7 +722,17 @@ void cdrInterrupt() { InuYasha - Feudal Fairy Tale: slower - Fixes battles */ - AddIrqQueue(CdlPause + 0x100, cdReadTime * 3); + /* Gameblabla - Tightening the timings (as taken from Mednafen). */ + if (cdr.DriveState != DRIVESTATE_STANDBY) + { + delay = 5000; + } + else + { + delay = (1124584 + (msf2sec(cdr.SetSectorPlay) * 42596 / (75 * 60))) * ((cdr.Mode & MODE_SPEED) ? 1 : 2); + CDRMISC_INT((cdr.Mode & MODE_SPEED) ? cdReadTime / 2 : cdReadTime); + } + AddIrqQueue(CdlPause + 0x100, delay); cdr.Ctrl |= 0x80; break; @@ -724,13 +742,15 @@ void cdrInterrupt() { cdr.Stat = Complete; break; - case CdlInit: - AddIrqQueue(CdlInit + 0x100, cdReadTime * 6); + case CdlReset: + cdr.Muted = FALSE; + cdr.Mode = 0x20; /* This fixes This is Football 2, Pooh's Party lockups */ + AddIrqQueue(CdlReset + 0x100, 4100000); no_busy_error = 1; start_rotating = 1; break; - case CdlInit + 0x100: + case CdlReset + 0x100: cdr.Stat = Complete; break; @@ -751,13 +771,13 @@ void cdrInterrupt() { no_busy_error = 1; break; - case CdlGetmode: - SetResultSize(6); + 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] = cdr.File; - cdr.Result[3] = cdr.Channel; - cdr.Result[4] = 0; - cdr.Result[5] = 0; + cdr.Result[2] = 0; + cdr.Result[3] = cdr.File; + cdr.Result[4] = cdr.Channel; no_busy_error = 1; break; @@ -807,7 +827,9 @@ void cdrInterrupt() { cdr.Result[0] = cdr.StatP; cdr.Result[1] = itob(cdr.ResultTD[2]); cdr.Result[2] = itob(cdr.ResultTD[1]); - cdr.Result[3] = itob(cdr.ResultTD[0]); + /* According to Nocash's documentation, the function doesn't care about ff. + * This can be seen also in Mednafen's implementation. */ + //cdr.Result[3] = itob(cdr.ResultTD[0]); } break; @@ -880,7 +902,7 @@ void cdrInterrupt() { cdr.Stat = Complete; break; - case CdlReset: + case CdlInit: // yes, it really sets STATUS_SHELLOPEN cdr.StatP |= STATUS_SHELLOPEN; cdr.DriveState = DRIVESTATE_RESCAN_CD; @@ -890,8 +912,7 @@ void cdrInterrupt() { break; case CdlGetQ: - // TODO? - CDR_LOG_I("got CdlGetQ\n"); + no_busy_error = 1; break; case CdlReadToc: @@ -908,8 +929,11 @@ void cdrInterrupt() { case CdlReadN: case CdlReadS: if (cdr.SetlocPending) { + seekTime = abs(msf2sec(cdr.SetSectorPlay) - msf2sec(cdr.SetSector)) * (cdReadTime / 200); + if(seekTime > 1000000) seekTime = 1000000; memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); cdr.SetlocPending = 0; + cdr.m_locationChanged = TRUE; } Find_CurTrack(cdr.SetSectorPlay); @@ -947,7 +971,7 @@ void cdrInterrupt() { // - fix cutscene speech (startup) // ??? - use more accurate seek time later - CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1); + CDREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1) + seekTime); } else { cdr.StatP |= STATUS_READ; cdr.StatP &= ~STATUS_SEEK; @@ -958,7 +982,7 @@ void cdrInterrupt() { cdr.Result[0] = cdr.StatP; start_rotating = 1; break; - + case CdlSync: default: CDR_LOG_I("Invalid command: %02x\n", Irq); error = ERROR_INVALIDCMD; @@ -984,7 +1008,7 @@ void cdrInterrupt() { case DRIVESTATE_PREPARE_CD: SetResultSize(2); cdr.Result[0] = cdr.StatP | STATUS_ERROR; - cdr.Result[1] = ERROR_NOT_READY; + cdr.Result[1] = ERROR_NOTREADY; cdr.Stat = DiskError; break; } @@ -1006,7 +1030,7 @@ finish: #endif } -#ifdef __ARM_ARCH_7A__ +#ifdef HAVE_ARMV7 #define ssat32_to_16(v) \ asm("ssat %0,#16,%1" : "=r" (v) : "r" (v)) #else @@ -1101,9 +1125,14 @@ void cdrReadInterrupt() { cdr.Channel = cdr.Transfer[4 + 1]; } + /* Gameblabla + * Skips playing on channel 255. + * Fixes missing audio in Blue's Clues : Blue's Big Musical. (Should also fix Taxi 2) + * TODO : Check if this is the proper behaviour. + * */ if((cdr.Transfer[4 + 2] & 0x4) && (cdr.Transfer[4 + 1] == cdr.Channel) && - (cdr.Transfer[4 + 0] == cdr.File)) { + (cdr.Transfer[4 + 0] == cdr.File) && cdr.Channel != 255) { int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); if (!ret) { cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo); @@ -1126,7 +1155,13 @@ void cdrReadInterrupt() { cdr.Readed = 0; - CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime); + uint32_t delay = (cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime; + if (cdr.m_locationChanged) { + CDREAD_INT(delay * 30); + cdr.m_locationChanged = FALSE; + } else { + CDREAD_INT(delay); + } /* Croc 2: $40 - only FORM1 (*) @@ -1231,17 +1266,29 @@ void cdrWrite1(unsigned char rt) { switch (cdr.Cmd) { case CdlSetloc: - for (i = 0; i < 3; i++) - set_loc[i] = btoi(cdr.Param[i]); + CDR_LOG("CDROM setloc command (%02X, %02X, %02X)\n", cdr.Param[0], cdr.Param[1], cdr.Param[2]); - i = msf2sec(cdr.SetSectorPlay); - i = abs(i - msf2sec(set_loc)); - if (i > 16) - cdr.Seeked = SEEK_PENDING; + // 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; + memcpy(cdr.SetSector, set_loc, 3); + cdr.SetSector[3] = 0; + cdr.SetlocPending = 1; + } break; case CdlReadN: @@ -1251,8 +1298,8 @@ void cdrWrite1(unsigned char rt) { StopReading(); break; - case CdlReset: case CdlInit: + case CdlReset: cdr.Seeked = SEEK_DONE; StopCdda(); StopReading(); @@ -1413,13 +1460,15 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { psxCpu->Clear(madr, cdsize / 4); pTransfer += cdsize; - - // burst vs normal if( chcr == 0x11400100 ) { + HW_DMA3_MADR = SWAPu32(madr + cdsize); CDRDMA_INT( (cdsize/4) / 4 ); } else if( chcr == 0x11000000 ) { - CDRDMA_INT( (cdsize/4) * 1 ); + // CDRDMA_INT( (cdsize/4) * 1 ); + // halted + psxRegs.cycle += (cdsize/4) * 24/2; + CDRDMA_INT(16); } return; @@ -1462,6 +1511,8 @@ 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; @@ -1495,7 +1546,9 @@ int cdrFreeze(void *f, int Mode) { pTransfer = cdr.Transfer + tmp; // read right sub data - memcpy(tmpp, cdr.Prev, 3); + tmpp[0] = btoi(cdr.Prev[0]); + tmpp[1] = btoi(cdr.Prev[1]); + tmpp[2] = btoi(cdr.Prev[2]); cdr.Prev[0]++; ReadTrack(tmpp); @@ -1514,6 +1567,12 @@ int cdrFreeze(void *f, int Mode) { SysPrintf("cdrom: fixing up old savestate\n"); cdr.Reg2 = 7; } + // also did not save Attenuator.. + if ((cdr.AttenuatorLeftToLeft | cdr.AttenuatorLeftToRight + | cdr.AttenuatorRightToLeft | cdr.AttenuatorRightToRight) == 0) + { + cdr.AttenuatorLeftToLeft = cdr.AttenuatorRightToRight = 0x80; + } } }