mirror of https://github.com/PCSX2/pcsx2.git
CDVD: Add some error handling, fix up some IRQ stuff
This commit is contained in:
parent
8dd51b7207
commit
7d9c8c9172
pcsx2/CDVD
|
@ -610,6 +610,13 @@ s32 cdvdReadSubQ(s32 lsn, cdvdSubQ* subq)
|
|||
static void cdvdDetectDisk()
|
||||
{
|
||||
cdvd.Type = DoCDVDdetectDiskType();
|
||||
|
||||
if (cdvd.Type != 0)
|
||||
{
|
||||
cdvdTD td;
|
||||
CDVD->getTD(0, &td);
|
||||
cdvd.MaxSector = td.lsn;
|
||||
}
|
||||
}
|
||||
|
||||
s32 cdvdCtrlTrayOpen()
|
||||
|
@ -1056,7 +1063,6 @@ __fi void cdvdActionInterrupt()
|
|||
cdvd.Sector = cdvd.SeekToSector;
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
break;
|
||||
|
||||
|
@ -1067,7 +1073,6 @@ __fi void cdvdActionInterrupt()
|
|||
cdvd.Sector = cdvd.SeekToSector;
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
break;
|
||||
|
||||
|
@ -1092,10 +1097,8 @@ __fi void cdvdActionInterrupt()
|
|||
break;
|
||||
}
|
||||
cdvd.Action = cdvdAction_None;
|
||||
cdvd.nCommand = 0;
|
||||
|
||||
cdvd.PwOff |= 1 << Irq_CommandComplete;
|
||||
psxHu32(0x1070) |= 0x4;
|
||||
cdvdSetIrq();
|
||||
}
|
||||
|
||||
__fi void cdvdSectorReady()
|
||||
|
@ -1104,19 +1107,6 @@ __fi void cdvdSectorReady()
|
|||
{
|
||||
cdvd.nextSectorsBuffered++;
|
||||
CDVD_LOG("Buffering sector");
|
||||
|
||||
//DevCon.Warning("Bufferred Sector %d cur seek %d ready %x", cdvd.Sector, cdvd.SeekToSector, cdvd.Ready);
|
||||
if (cdvd.nextSectorsBuffered == 16 && cdvd.triggerDataReady)
|
||||
{
|
||||
CDVD_LOG("Interrupting to say data ready");
|
||||
if (!(cdvd.PwOff & (1 << Irq_DataReady)))
|
||||
{
|
||||
cdvd.PwOff |= (1 << Irq_DataReady);
|
||||
iopIntcIrq(2);
|
||||
}
|
||||
cdvd.Ready |= CDVD_DRIVE_DATARDY;
|
||||
cdvd.triggerDataReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cdvd.nextSectorsBuffered < 16)
|
||||
|
@ -1214,14 +1204,10 @@ __fi void cdvdReadInterrupt()
|
|||
{
|
||||
// Setting the data ready flag fixes a black screen loading issue in
|
||||
// Street Fighter Ex3 (NTSC-J version).
|
||||
cdvd.PwOff |= (1 << Irq_CommandComplete) | (1 << Irq_DataReady);
|
||||
//psxHu32(0x1070) |= 0x4;
|
||||
iopIntcIrq(2);
|
||||
cdvdSetIrq();
|
||||
cdvd.Ready |= CDVD_DRIVE_READY;
|
||||
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
|
||||
cdvd.nCommand = 0;
|
||||
//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.
|
||||
|
@ -1235,24 +1221,12 @@ __fi void cdvdReadInterrupt()
|
|||
{
|
||||
if (cdvd.nSectors <= 0)
|
||||
{
|
||||
cdvd.PwOff |= (1 << Irq_CommandComplete) | (1 << Irq_DataReady);
|
||||
cdvdSetIrq();
|
||||
//psxHu32(0x1070) |= 0x4;
|
||||
iopIntcIrq(2);
|
||||
cdvd.Ready |= CDVD_DRIVE_READY;
|
||||
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
|
||||
cdvd.nCommand = 0;
|
||||
|
||||
if (!HW_DMA3_BCR_H16)
|
||||
{
|
||||
if (HW_DMA3_CHCR & 0x01000000)
|
||||
{
|
||||
HW_DMA3_CHCR &= ~0x01000000;
|
||||
psxDmaInterrupt(3);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
CDVDREAD_INT((cdvd.BlockSize / 4) * 12);
|
||||
|
@ -1280,7 +1254,6 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
|||
cdvd.Ready &= ~(CDVD_DRIVE_READY | CDVD_DRIVE_DATARDY);
|
||||
cdvd.Reading = 1;
|
||||
cdvd.Readed = 0;
|
||||
cdvd.triggerDataReady = false;
|
||||
// Okay so let's explain this, since people keep messing with it in the past and just poking it.
|
||||
// So when the drive is spinning, bit 0x2 is set on the Status, and bit 0x8 is set when the drive is not reading.
|
||||
// So In the case where it's seeking to data it will be Spinning (0x2) not reading (0x8) and Seeking (0x10, but because seeking is also spinning 0x2 is also set))
|
||||
|
@ -1607,6 +1580,27 @@ u8 cdvdRead(u8 key)
|
|||
}
|
||||
}
|
||||
|
||||
static bool cdvdReadErrorHandler()
|
||||
{
|
||||
if (cdvd.nSectors <= 0)
|
||||
{
|
||||
DevCon.Warning("Bad Sector Count Error");
|
||||
cdvd.Error = 0x21; // Number of read sectors abnormal
|
||||
cdvdSetIrq();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cdvd.SeekToSector > cdvd.MaxSector)
|
||||
{
|
||||
DevCon.Warning("Invalid Sector Error");
|
||||
cdvd.Error = 0x20; // Sector position is abnormal
|
||||
cdvdSetIrq();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cdvdWrite04(u8 rt)
|
||||
{ // NCOMMAND
|
||||
CDVD_LOG("cdvdWrite04: NCMD %s (%x) (ParamP = %x)", nCmdName[rt], rt, cdvd.ParamP);
|
||||
|
@ -1638,7 +1632,6 @@ static void cdvdWrite04(u8 rt)
|
|||
DevCon.Warning("CdStop : %d", rt);
|
||||
cdvd.Action = cdvdAction_Stop;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
psxRegs.interrupt &= ~(1 << IopEvt_CdvdSectorReady);
|
||||
cdvd.Status = CDVD_STATUS_SPIN;
|
||||
CDVD_INT(PSXCLK / 6); // 166ms delay?
|
||||
|
@ -1650,11 +1643,9 @@ static void cdvdWrite04(u8 rt)
|
|||
psxRegs.interrupt &= ~(1 << IopEvt_Cdvd);
|
||||
cdvd.Ready |= CDVD_DRIVE_READY;
|
||||
cdvdSetIrq();
|
||||
cdvd.nCommand = 0;
|
||||
//After Pausing needs to buffer the next sector
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
break;
|
||||
|
||||
|
@ -1729,6 +1720,9 @@ static void cdvdWrite04(u8 rt)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!cdvdReadErrorHandler())
|
||||
break;
|
||||
|
||||
CDVD_LOG("CDRead > startSector=%d, seekTo=%d nSectors=%d, RetryCnt=%x, Speed=%dx(%s), ReadMode=%x(%x) SpindleCtrl=%x",
|
||||
cdvd.Sector, cdvd.SeekToSector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, (cdvd.SpindlCtrl & CDVD_SPINDLE_CAV) ? L"CAV" : L"CLV", cdvd.ReadMode, cdvd.Param[10], cdvd.SpindlCtrl);
|
||||
|
||||
|
@ -1850,6 +1844,9 @@ static void cdvdWrite04(u8 rt)
|
|||
cdvd.ReadMode = CDVD_MODE_2048;
|
||||
cdvd.BlockSize = 2064;
|
||||
|
||||
if (!cdvdReadErrorHandler())
|
||||
break;
|
||||
|
||||
CDVD_LOG("DvdRead > startSector=%d, seekTo=%d nSectors=%d, RetryCnt=%x, Speed=%dx(%s), ReadMode=%x(%x) SpindleCtrl=%x",
|
||||
cdvd.Sector, cdvd.SeekToSector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, (cdvd.SpindlCtrl & CDVD_SPINDLE_CAV) ? L"CAV" : L"CLV", cdvd.ReadMode, cdvd.Param[10], cdvd.SpindlCtrl);
|
||||
|
||||
|
@ -1880,13 +1877,11 @@ static void cdvdWrite04(u8 rt)
|
|||
//}
|
||||
cdvdGetToc(iopPhysMem(HW_DMA3_MADR));
|
||||
cdvdSetIrq();
|
||||
cdvd.nCommand = 0;
|
||||
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;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
break;
|
||||
|
||||
|
@ -1899,11 +1894,9 @@ static void cdvdWrite04(u8 rt)
|
|||
cdvdReadKey(arg0, arg1, arg2, cdvd.Key);
|
||||
cdvd.KeyXor = 0x00;
|
||||
cdvdSetIrq();
|
||||
cdvd.nCommand = 0;
|
||||
//After reading the key it needs to go back to buffer the next sector
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
}
|
||||
break;
|
||||
|
@ -1911,13 +1904,11 @@ static void cdvdWrite04(u8 rt)
|
|||
case N_CD_CHG_SPDL_CTRL: // CdChgSpdlCtrl
|
||||
Console.WriteLn("sceCdChgSpdlCtrl(%d)", cdvd.Param[0]);
|
||||
cdvdSetIrq();
|
||||
cdvd.nCommand = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
Console.Warning("NCMD Unknown %x", rt);
|
||||
cdvdSetIrq();
|
||||
cdvd.nCommand = 0;
|
||||
break;
|
||||
}
|
||||
cdvd.ParamP = 0;
|
||||
|
@ -1963,18 +1954,12 @@ static __fi void cdvdWrite07(u8 rt) // BREAK
|
|||
cdvd.Readed = 0;
|
||||
cdvd.Reading = 0;
|
||||
cdvd.Status = CDVD_STATUS_STOP;
|
||||
//cdvd.nCommand = 0;
|
||||
}
|
||||
|
||||
static __fi void cdvdWrite08(u8 rt)
|
||||
{ // INTR_STAT
|
||||
CDVD_LOG("cdvdWrite08(IntrReason) = ACK(%x)", rt);
|
||||
cdvd.PwOff &= ~rt;
|
||||
if (rt & (1 << Irq_DataReady))
|
||||
{
|
||||
CDVD_LOG("Data ready acknowledged");
|
||||
cdvd.Ready &= ~CDVD_DRIVE_DATARDY;
|
||||
}
|
||||
}
|
||||
|
||||
static __fi void cdvdWrite0A(u8 rt)
|
||||
|
|
|
@ -148,12 +148,12 @@ struct cdvdStruct
|
|||
u8 TrayTimeout;
|
||||
u8 Action; // the currently scheduled emulated action
|
||||
u32 SeekToSector; // Holds the destination sector during seek operations.
|
||||
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;
|
||||
bool triggerDataReady;
|
||||
};
|
||||
|
||||
extern cdvdStruct cdvd;
|
||||
|
|
|
@ -38,6 +38,8 @@ without proper emulation of the cdvd status flag it also tends to break things.
|
|||
|
||||
*/
|
||||
|
||||
/* Old IRQ structure
|
||||
|
||||
enum CdvdIrqId
|
||||
{
|
||||
Irq_None = 0,
|
||||
|
@ -49,6 +51,16 @@ enum CdvdIrqId
|
|||
Irq_NotReady
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
enum CdvdIrqId
|
||||
{
|
||||
Irq_None = 0,
|
||||
Irq_CommandComplete = 0,
|
||||
Irq_POffReady = 2,
|
||||
Irq_Eject,
|
||||
Irq_BSPower, //PS1 IRQ not used
|
||||
};
|
||||
|
||||
/* Cdvd.Status bits and their meaning
|
||||
0x0 = Stop
|
||||
|
|
|
@ -1074,6 +1074,9 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr)
|
|||
|
||||
break;
|
||||
case 0x41000200:
|
||||
if (HW_DMA3_BCR_H16 == 0)
|
||||
break;
|
||||
|
||||
if (cdvd.WaitingDMA)
|
||||
{
|
||||
PSX_INT(IopEvt_CdvdRead, (cdvd.BlockSize / 4) * 12); //Data should be already buffered so simulate DMA time
|
||||
|
|
Loading…
Reference in New Issue