diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index b9f798f4e7..471b9c5bad 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -619,6 +619,12 @@ static void cdvdDetectDisk() } } +static void cdvdUpdateStatus(cdvdStatus NewStatus) +{ + cdvd.Status = NewStatus; + cdvd.StatusSticky |= NewStatus; +} + s32 cdvdCtrlTrayOpen() { DevCon.WriteLn(Color_Green, L"Open virtual disk tray"); @@ -633,11 +639,9 @@ s32 cdvdCtrlTrayOpen() cdvdDetectDisk(); DiscSwapTimerSeconds = cdvd.RTC.second; // remember the PS2 time when this happened - cdvd.Status = CDVD_STATUS_TRAY_OPEN; + cdvdUpdateStatus(CDVD_STATUS_TRAY_OPEN); cdvd.Ready = CDVD_DRIVE_BUSY | CDVD_DRIVE_DEV9CON; - cdvd.mediaChanged = true; - if (cdvd.Type > 0 || CDVDsys_GetSourceType() == CDVD_SourceType::NoDisc) { cdvd.Tray.cdvdActionSeconds = 3; @@ -656,7 +660,7 @@ s32 cdvdCtrlTrayClose() { DevCon.WriteLn(Color_Green, L"Media already loaded (fast boot)"); cdvd.Ready = CDVD_DRIVE_READY | CDVD_DRIVE_DEV9CON; - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); cdvd.Tray.trayState = CDVD_DISC_ENGAGED; cdvd.Tray.cdvdActionSeconds = 0; } @@ -664,7 +668,7 @@ s32 cdvdCtrlTrayClose() { DevCon.WriteLn(Color_Green, L"Detecting media"); cdvd.Ready = CDVD_DRIVE_BUSY | CDVD_DRIVE_DEV9CON; - cdvd.Status = CDVD_STATUS_SEEK; + cdvdUpdateStatus(CDVD_STATUS_SEEK); cdvd.Tray.trayState = CDVD_DISC_DETECTING; cdvd.Tray.cdvdActionSeconds = 3; } @@ -812,7 +816,7 @@ void cdvdReset() cdvd.sDataIn = 0x40; cdvd.Ready = CDVD_DRIVE_READY | CDVD_DRIVE_DEV9CON; - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); cdvd.Speed = 4; cdvd.BlockSize = 2064; cdvd.Action = cdvdAction_None; @@ -904,10 +908,9 @@ void cdvdNewDiskCB() if ((g_GameStarted || !g_SkipBiosHack) && cdvd.Tray.trayState != CDVD_DISC_EJECT) { DevCon.WriteLn(Color_Green, L"Ejecting media"); - cdvd.Status = CDVD_STATUS_TRAY_OPEN; + cdvdUpdateStatus(CDVD_STATUS_TRAY_OPEN); cdvd.Ready = CDVD_DRIVE_BUSY | CDVD_DRIVE_DEV9CON; cdvd.Tray.trayState = CDVD_DISC_EJECT; - cdvd.mediaChanged = true; // If it really got ejected, the DVD Reader will report Type 0, so no need to simulate ejection if (cdvd.Type > 0) @@ -917,7 +920,7 @@ void cdvdNewDiskCB() { DevCon.WriteLn(Color_Green, L"Seeking new media"); cdvd.Ready = CDVD_DRIVE_BUSY | CDVD_DRIVE_DEV9CON; - cdvd.Status = CDVD_STATUS_SEEK; + cdvdUpdateStatus(CDVD_STATUS_SEEK); cdvd.Tray.trayState = CDVD_DISC_DETECTING; cdvd.Tray.cdvdActionSeconds = 3; } @@ -1061,7 +1064,7 @@ __fi void cdvdActionInterrupt() cdvd.Spinning = true; cdvd.Ready = CDVD_DRIVE_READY | CDVD_DRIVE_DEV9CON; cdvd.Sector = cdvd.SeekToSector; - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); cdvd.nextSectorsBuffered = 0; CDVDSECTORREADY_INT(cdvd.ReadTime); break; @@ -1071,7 +1074,7 @@ __fi void cdvdActionInterrupt() cdvd.Spinning = true; //check (rama) cdvd.Ready = CDVD_DRIVE_READY | CDVD_DRIVE_DEV9CON; cdvd.Sector = cdvd.SeekToSector; - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); cdvd.nextSectorsBuffered = 0; CDVDSECTORREADY_INT(cdvd.ReadTime); break; @@ -1080,7 +1083,7 @@ __fi void cdvdActionInterrupt() cdvd.Spinning = false; cdvd.Ready = CDVD_DRIVE_READY | CDVD_DRIVE_DEV9CON; cdvd.Sector = 0; - cdvd.Status = CDVD_STATUS_STOP; + cdvdUpdateStatus(CDVD_STATUS_STOP); break; case cdvdAction_Break: @@ -1092,7 +1095,7 @@ __fi void cdvdActionInterrupt() cdvd.Reading = 0; cdvd.Readed = 0; cdvd.Ready = CDVD_DRIVE_READY | CDVD_DRIVE_DEV9CON | CDVD_DRIVE_ERROR; // should be CDVD_READY1 or something else? - cdvd.Status = CDVD_STATUS_PAUSE; //Break stops the command in progress it doesn't stop the drive. Formula 2001 + cdvdUpdateStatus(CDVD_STATUS_PAUSE); cdvd.RErr = 0; break; } @@ -1119,7 +1122,7 @@ __fi void cdvdReadInterrupt() //Console.WriteLn("cdvdReadInterrupt %x %x %x %x %x", cpuRegs.interrupt, cdvd.Readed, cdvd.Reading, cdvd.nSectors, (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4); cdvd.Ready = CDVD_DRIVE_BUSY | CDVD_DRIVE_DEV9CON; - cdvd.Status = CDVD_STATUS_READ; + cdvdUpdateStatus(CDVD_STATUS_READ); cdvd.WaitingDMA = false; if (!cdvd.Readed) @@ -1189,7 +1192,7 @@ __fi void cdvdReadInterrupt() psxHu32(0x1070) |= 0x4; cdvd.Ready |= CDVD_DRIVE_DATARDY; }*/ - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); cdvd.WaitingDMA = true; return; } @@ -1207,7 +1210,7 @@ __fi void cdvdReadInterrupt() cdvdSetIrq(); cdvd.Ready = CDVD_DRIVE_READY | CDVD_DRIVE_DEV9CON; - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); //DevCon.Warning("Scheduling interrupt in %d cycles", cdvd.ReadTime - ((cdvd.BlockSize / 4) * 12)); // Timing issues on command end // Star Ocean (1.1 Japan) expects the DMA to end and interrupt at least 128 or more cycles before the CDVD command ends. @@ -1226,7 +1229,7 @@ __fi void cdvdReadInterrupt() iopIntcIrq(2); cdvd.Ready = CDVD_DRIVE_READY | CDVD_DRIVE_DEV9CON; - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); return; } CDVDREAD_INT((cdvd.BlockSize / 4) * 12); @@ -1260,7 +1263,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode) // Update - Apparently all that was rubbish and some games don't like it. WRC was the one in this scenario which hated SEEK |ZPAUSE, so just putting it back to pause for now. // We should really run some tests for this behaviour. - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); if (!cdvd.Spinning) { @@ -1299,7 +1302,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode) if (delta == 0) { //cdvd.Status = CDVD_STATUS_PAUSE; - cdvd.Status = CDVD_STATUS_READ; // Time Crisis 2 + cdvdUpdateStatus(CDVD_STATUS_READ); cdvd.Readed = 1; // Note: 1, not 0, as implied by the next comment. Need to look into this. --arcum42 cdvd.Reading = 1; // We don't need to wait for it to read a sector as it's already queued up, or we adjust for it here. cdvd.RetryCntP = 0; @@ -1372,11 +1375,12 @@ void cdvdUpdateTrayState() if (CDVDsys_GetSourceType() != CDVD_SourceType::NoDisc) { DevCon.WriteLn(Color_Green, L"Media ready to read"); - cdvd.mediaChanged = true; - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); } else - cdvd.Status = CDVD_STATUS_STOP; + { + cdvdUpdateStatus(CDVD_STATUS_STOP); + } break; } } @@ -1470,13 +1474,10 @@ u8 cdvdRead(u8 key) CDVD_LOG("cdvdRead0A(Status) %x", cdvd.Status); return cdvd.Status; - case 0x0B: // MEDIA CHANGED (Set when disc is ejected or detected, aka cdvd.type changes) + case 0x0B: // STATUS STICKY { - CDVD_LOG("cdvdRead0B(Media Change) (1 Changed, 0 Not Changed): %x", cdvd.mediaChanged); - bool ret = cdvd.mediaChanged; - cdvd.mediaChanged = false; - - return ret; + CDVD_LOG("cdvdRead0B(Status Sticky): %x", cdvd.StatusSticky); + return cdvd.StatusSticky; } case 0x0C: // CRT MINUTE CDVD_LOG("cdvdRead0C(Min) %x", itob((u8)(cdvd.Sector / (60 * 75)))); @@ -1627,7 +1628,7 @@ static void cdvdWrite04(u8 rt) CDVD_INT(cdvdStartSeek(0, MODE_DVDROM)); // Might not seek, but makes sense since it does move to the inner most track // It's only temporary until the interrupt anyway when it sets itself ready - cdvd.Status = CDVD_STATUS_SEEK; + cdvdUpdateStatus(CDVD_STATUS_SEEK); break; case N_CD_STOP: // CdStop @@ -1635,7 +1636,7 @@ static void cdvdWrite04(u8 rt) cdvd.Action = cdvdAction_Stop; cdvd.nextSectorsBuffered = 0; psxRegs.interrupt &= ~(1 << IopEvt_CdvdSectorReady); - cdvd.Status = CDVD_STATUS_SPIN; + cdvdUpdateStatus(CDVD_STATUS_SPIN); CDVD_INT(PSXCLK / 6); // 166ms delay? break; @@ -1646,7 +1647,7 @@ static void cdvdWrite04(u8 rt) cdvd.Ready = CDVD_DRIVE_READY | CDVD_DRIVE_DEV9CON; cdvdSetIrq(); //After Pausing needs to buffer the next sector - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); cdvd.nextSectorsBuffered = 0; CDVDSECTORREADY_INT(cdvd.ReadTime); break; @@ -1655,7 +1656,7 @@ static void cdvdWrite04(u8 rt) cdvd.Action = cdvdAction_Seek; cdvd.ReadTime = cdvdBlockReadTime((CDVD_MODE_TYPE)cdvdIsDVD()); CDVD_INT(cdvdStartSeek(*(uint*)(cdvd.Param + 0), (CDVD_MODE_TYPE)cdvdIsDVD())); - cdvd.Status = CDVD_STATUS_SEEK; + cdvdUpdateStatus(CDVD_STATUS_SEEK); break; case N_CD_READ: // CdRead @@ -1882,7 +1883,7 @@ static void cdvdWrite04(u8 rt) HW_DMA3_CHCR &= ~0x01000000; psxDmaInterrupt(3); //After reading the TOC it needs to go back to buffer the next sector - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); cdvd.nextSectorsBuffered = 0; CDVDSECTORREADY_INT(cdvd.ReadTime); break; @@ -1897,7 +1898,7 @@ static void cdvdWrite04(u8 rt) cdvd.KeyXor = 0x00; cdvdSetIrq(); //After reading the key it needs to go back to buffer the next sector - cdvd.Status = CDVD_STATUS_PAUSE; + cdvdUpdateStatus(CDVD_STATUS_PAUSE); cdvd.nextSectorsBuffered = 0; CDVDSECTORREADY_INT(cdvd.ReadTime); } @@ -1955,7 +1956,7 @@ static __fi void cdvdWrite07(u8 rt) // BREAK // Clear the cdvd status: cdvd.Readed = 0; cdvd.Reading = 0; - cdvd.Status = CDVD_STATUS_STOP; + cdvdUpdateStatus(CDVD_STATUS_STOP); } static __fi void cdvdWrite08(u8 rt) @@ -2066,27 +2067,13 @@ static void cdvdWrite16(u8 rt) // SCOMMAND } break; - case 0x05: // CdTrayReqState (0:1) - resets the tray open detection - - // Fixme: This function is believed to change some status flag - // when the Tray state (stored as "1" in cdvd.Status) is different between 2 successive calls. - // Cdvd.Status can be different than 1 here, yet we may still have to report an open status. - // Gonna have to investigate further. (rama) - + case 0x05: // CdTrayReqState (0:1) - resets the tray open detection //Console.Warning("CdTrayReqState. cdvd.Status = %d", cdvd.Status); + // This function sets the Sticky tray flag to the same value as Status for detecting change + cdvd.StatusSticky = cdvd.Status & CDVD_STATUS_TRAY_OPEN; + SetResultSize(1); - - if (cdvd.Status == CDVD_STATUS_TRAY_OPEN) - { - //Console.Warning( "reporting Open status" ); - cdvd.Result[0] = 1; - } - else - { - //Console.Warning( "reporting Close status" ); - cdvd.Result[0] = 0; // old behaviour was always this - } - + cdvd.Result[0] = 0; // Could be a bit to say it's busy, but actual function is unknown, it expects 0 to continue. break; case 0x06: // CdTrayCtrl (1:1) diff --git a/pcsx2/CDVD/CDVD.h b/pcsx2/CDVD/CDVD.h index 0c26712594..5770a07402 100644 --- a/pcsx2/CDVD/CDVD.h +++ b/pcsx2/CDVD/CDVD.h @@ -97,6 +97,7 @@ struct cdvdStruct u8 Error; u8 PwOff; u8 Status; + u8 StatusSticky; u8 Type; u8 sCommand; u8 sDataIn; @@ -151,7 +152,6 @@ struct cdvdStruct u32 MaxSector; // Current disc max sector. u32 ReadTime; // Avg. time to read one block of data (in Iop cycles) bool Spinning; // indicates if the Cdvd is spinning or needs a spinup delay - bool mediaChanged; cdvdTrayTimer Tray; u8 nextSectorsBuffered; };