mirror of https://github.com/PCSX2/pcsx2.git
CDVD: Added simple rotational latency
Also removed DMA delay
This commit is contained in:
parent
6bed14cb26
commit
b8f4a8ffb3
|
@ -47,17 +47,6 @@ static __fi void SetResultSize(u8 size)
|
||||||
cdvd.sDataIn &= ~0x40;
|
cdvd.sDataIn &= ~0x40;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CDVDDMA_INT(u32 eCycle)
|
|
||||||
{
|
|
||||||
if (EmuConfig.Speedhacks.fastCDVD)
|
|
||||||
{
|
|
||||||
if (eCycle < Cdvd_FullSeek_Cycles && eCycle > 1)
|
|
||||||
eCycle *= 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
PSX_INT(IopEvt_CdvdDMA, eCycle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CDVDREAD_INT(u32 eCycle)
|
static void CDVDREAD_INT(u32 eCycle)
|
||||||
{
|
{
|
||||||
// Give it an arbitary FAST value. Good for ~5000kb/s in ULE when copying a file from CDVD to HDD
|
// Give it an arbitary FAST value. Good for ~5000kb/s in ULE when copying a file from CDVD to HDD
|
||||||
|
@ -657,6 +646,53 @@ static bool cdvdIsDVD()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint cdvdRotationalLatency(CDVD_MODE_TYPE mode)
|
||||||
|
{
|
||||||
|
// CAV rotation is constant (minimum speed to maintain exact speed on outer dge
|
||||||
|
if (cdvd.SpindlCtrl & CDVD_SPINDLE_CAV)
|
||||||
|
{
|
||||||
|
float rotationPerSecond = (((mode == MODE_CDROM) ? CD_MIN_ROTATION_X1 : DVD_MIN_ROTATION_X1) * cdvd.Speed) / 60;
|
||||||
|
float msPerRotation = 1000.0f / rotationPerSecond;
|
||||||
|
return ((PSXCLK / 1000) * msPerRotation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int numSectors = 0;
|
||||||
|
int offset = 0;
|
||||||
|
//CLV adjusts its speed based on where it is on the disc, so we can take the max RPM and use the sector to work it out
|
||||||
|
// Sector counts are taken from google for Single layer, Dual layer DVD's and for 700MB CD's
|
||||||
|
switch (cdvd.Type)
|
||||||
|
{
|
||||||
|
case CDVD_TYPE_DETCTDVDS:
|
||||||
|
case CDVD_TYPE_PS2DVD:
|
||||||
|
numSectors = 2298496;
|
||||||
|
break;
|
||||||
|
case CDVD_TYPE_DETCTDVDD:
|
||||||
|
numSectors = 4173824 / 2; // Total sectors for both layers, assume half per layer
|
||||||
|
u32 layer1Start;
|
||||||
|
s32 dualType;
|
||||||
|
|
||||||
|
// Layer 1 needs an offset as it goes back to the middle of the disc
|
||||||
|
cdvdReadDvdDualInfo(&dualType, &layer1Start);
|
||||||
|
if (cdvd.SeekToSector >= layer1Start)
|
||||||
|
offset = layer1Start;
|
||||||
|
break;
|
||||||
|
default: // Pretty much every CD format
|
||||||
|
numSectors = 360000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float sectorSpeed = 1.0f - (((float)(cdvd.SeekToSector - offset) / numSectors) * 0.60f);
|
||||||
|
|
||||||
|
float rotationPerSecond = (((mode == MODE_CDROM) ? CD_MAX_ROTATION_X1 : DVD_MAX_ROTATION_X1) * cdvd.Speed * sectorSpeed) / 60;
|
||||||
|
float msPerRotation = 1000.0f / rotationPerSecond;
|
||||||
|
|
||||||
|
//DevCon.Warning("Rotations per second %f, msPerRotation cycles per ms %f total cycles per ms %d cycles per rotation %d", rotationPerSecond, msPerRotation, (u32)(PSXCLK / 1000), (u32)((PSXCLK / 1000) * msPerRotation));
|
||||||
|
|
||||||
|
return ((PSXCLK / 1000) * msPerRotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint cdvdBlockReadTime(CDVD_MODE_TYPE mode)
|
static uint cdvdBlockReadTime(CDVD_MODE_TYPE mode)
|
||||||
{
|
{
|
||||||
int numSectors = 0;
|
int numSectors = 0;
|
||||||
|
@ -815,11 +851,11 @@ int cdvdReadSector()
|
||||||
if (bcr < cdvd.BlockSize)
|
if (bcr < cdvd.BlockSize)
|
||||||
{
|
{
|
||||||
CDVD_LOG("READBLOCK: bcr < cdvd.BlockSize; %x < %x", bcr, cdvd.BlockSize);
|
CDVD_LOG("READBLOCK: bcr < cdvd.BlockSize; %x < %x", bcr, cdvd.BlockSize);
|
||||||
/*if (HW_DMA3_CHCR & 0x01000000)
|
if (HW_DMA3_CHCR & 0x01000000)
|
||||||
{
|
{
|
||||||
HW_DMA3_CHCR &= ~0x01000000;
|
HW_DMA3_CHCR &= ~0x01000000;
|
||||||
psxDmaInterrupt(3);
|
psxDmaInterrupt(3);
|
||||||
}*/
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -953,23 +989,6 @@ __fi void cdvdActionInterrupt()
|
||||||
psxHu32(0x1070) |= 0x4;
|
psxHu32(0x1070) |= 0x4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cdvdDMAInterrupt()
|
|
||||||
{
|
|
||||||
if (HW_DMA3_CHCR & 0x01000000)
|
|
||||||
{
|
|
||||||
HW_DMA3_CHCR &= ~0x01000000;
|
|
||||||
psxDmaInterrupt(3);
|
|
||||||
|
|
||||||
if (!cdvd.nSectors)
|
|
||||||
{
|
|
||||||
// Setting the data ready flag fixes a black screen loading issue in
|
|
||||||
// Street Fighter Ex3 (NTSC-J version).
|
|
||||||
cdvd.PwOff |= (1 << Irq_DataReady) | (1 << Irq_CommandComplete);
|
|
||||||
psxHu32(0x1070) |= 0x4;
|
|
||||||
cdvd.Ready = CDVD_READY2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// inlined due to being referenced in only one place.
|
// inlined due to being referenced in only one place.
|
||||||
__fi void cdvdReadInterrupt()
|
__fi void cdvdReadInterrupt()
|
||||||
{
|
{
|
||||||
|
@ -1040,13 +1059,8 @@ __fi void cdvdReadInterrupt()
|
||||||
// bit and try to read the sector again later.
|
// bit and try to read the sector again later.
|
||||||
// An arbitrary delay of some number of cycles probably makes more sense here,
|
// An arbitrary delay of some number of cycles probably makes more sense here,
|
||||||
// but for now it's based on the cdvd.ReadTime value. -- air
|
// but for now it's based on the cdvd.ReadTime value. -- air
|
||||||
int DMATime = (cdvd.BlockSize / 2) * 40;
|
|
||||||
|
|
||||||
CDVDREAD_INT(DMATime + 100); // Bring it back after the DMA has ended to avoid a nasty loop
|
|
||||||
pxAssert((int)cdvd.ReadTime > 0);
|
pxAssert((int)cdvd.ReadTime > 0);
|
||||||
|
CDVDREAD_INT(cdvd.ReadTime); // Bring it back after the DMA has ended to avoid a nasty loop
|
||||||
if (HW_DMA3_CHCR & 0x01000000)
|
|
||||||
CDVDDMA_INT(DMATime);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1055,10 +1069,16 @@ __fi void cdvdReadInterrupt()
|
||||||
|
|
||||||
if (--cdvd.nSectors <= 0)
|
if (--cdvd.nSectors <= 0)
|
||||||
{
|
{
|
||||||
int DMATime = (cdvd.BlockSize / 2) * 40;
|
if (HW_DMA3_CHCR & 0x01000000)
|
||||||
|
{
|
||||||
CDVDDMA_INT(DMATime);
|
HW_DMA3_CHCR &= ~0x01000000;
|
||||||
|
psxDmaInterrupt(3);
|
||||||
|
}
|
||||||
|
// Setting the data ready flag fixes a black screen loading issue in
|
||||||
|
// Street Fighter Ex3 (NTSC-J version).
|
||||||
|
cdvd.PwOff |= (1 << Irq_DataReady) | (1 << Irq_CommandComplete);
|
||||||
|
psxHu32(0x1070) |= 0x4;
|
||||||
|
cdvd.Ready = CDVD_READY2;
|
||||||
cdvd.Status = CDVD_STATUS_PAUSE; // Needed here but could be smth else than Pause (rama)
|
cdvd.Status = CDVD_STATUS_PAUSE; // Needed here but could be smth else than Pause (rama)
|
||||||
// All done! :D
|
// All done! :D
|
||||||
return;
|
return;
|
||||||
|
@ -1118,7 +1138,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||||
CDVD_LOG("CdSeek Begin > Contiguous block without seek - delta=%d sectors", delta);
|
CDVD_LOG("CdSeek Begin > Contiguous block without seek - delta=%d sectors", delta);
|
||||||
|
|
||||||
// seektime is the time it takes to read to the destination block:
|
// seektime is the time it takes to read to the destination block:
|
||||||
seektime = delta * cdvd.ReadTime;
|
seektime = cdvd.ReadTime;
|
||||||
|
|
||||||
if (delta == 0)
|
if (delta == 0)
|
||||||
{
|
{
|
||||||
|
@ -1131,10 +1151,17 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||||
// cdvdReadInterrupt will load a block. So make sure it's properly scheduled
|
// cdvdReadInterrupt will load a block. So make sure it's properly scheduled
|
||||||
// based on sector read speeds:
|
// based on sector read speeds:
|
||||||
|
|
||||||
seektime = cdvd.ReadTime;
|
//seektime = cdvd.ReadTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (delta)
|
||||||
|
{
|
||||||
|
int rotationalLatency = cdvdRotationalLatency((CDVD_MODE_TYPE)cdvdIsDVD());
|
||||||
|
//DevCon.Warning("%s rotational latency at sector %d is %d cycles", (cdvd.SpindlCtrl & CDVD_SPINDLE_CAV) ? "CAV" : "CLV", cdvd.SeekToSector, rotationalLatency);
|
||||||
|
seektime += rotationalLatency;
|
||||||
|
}
|
||||||
|
|
||||||
return seektime;
|
return seektime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,12 @@ static const uint PSX_DVD_READSPEED = 1382400; // Bytes per second, rough values
|
||||||
static const uint CD_SECTORS_PERSECOND = 75;
|
static const uint CD_SECTORS_PERSECOND = 75;
|
||||||
static const uint DVD_SECTORS_PERSECOND = 675;
|
static const uint DVD_SECTORS_PERSECOND = 675;
|
||||||
|
|
||||||
|
static const uint CD_MIN_ROTATION_X1 = 214;
|
||||||
|
static const uint CD_MAX_ROTATION_X1 = 497;
|
||||||
|
|
||||||
|
static const uint DVD_MIN_ROTATION_X1 = 570;
|
||||||
|
static const uint DVD_MAX_ROTATION_X1 = 1515;
|
||||||
|
|
||||||
// Legacy Note: FullSeek timing causes many games to load very slow, but it likely not the real problem.
|
// Legacy Note: FullSeek timing causes many games to load very slow, but it likely not the real problem.
|
||||||
// Games breaking with it set to PSXCLK*40 : "wrath unleashed" and "Shijou Saikyou no Deshi Kenichi".
|
// Games breaking with it set to PSXCLK*40 : "wrath unleashed" and "Shijou Saikyou no Deshi Kenichi".
|
||||||
|
|
||||||
|
|
|
@ -320,7 +320,6 @@ enum IopEventId
|
||||||
IopEvt_CdvdRead,
|
IopEvt_CdvdRead,
|
||||||
IopEvt_DEV9,
|
IopEvt_DEV9,
|
||||||
IopEvt_USB,
|
IopEvt_USB,
|
||||||
IopEvt_CdvdDMA,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void PSX_INT( IopEventId n, s32 ecycle);
|
extern void PSX_INT( IopEventId n, s32 ecycle);
|
||||||
|
|
|
@ -178,7 +178,6 @@ static __fi void _psxTestInterrupts()
|
||||||
IopTestEvent(IopEvt_SIF2, sif2Interrupt); // SIF2
|
IopTestEvent(IopEvt_SIF2, sif2Interrupt); // SIF2
|
||||||
// Originally controlled by a preprocessor define, now PSX dependent.
|
// Originally controlled by a preprocessor define, now PSX dependent.
|
||||||
if (psxHu32(HW_ICFG) & (1 << 3)) IopTestEvent(IopEvt_SIO, sioInterruptR);
|
if (psxHu32(HW_ICFG) & (1 << 3)) IopTestEvent(IopEvt_SIO, sioInterruptR);
|
||||||
IopTestEvent(IopEvt_CdvdDMA, cdvdDMAInterrupt);
|
|
||||||
IopTestEvent(IopEvt_CdvdRead, cdvdReadInterrupt);
|
IopTestEvent(IopEvt_CdvdRead, cdvdReadInterrupt);
|
||||||
|
|
||||||
// Profile-guided Optimization (sorta)
|
// Profile-guided Optimization (sorta)
|
||||||
|
|
Loading…
Reference in New Issue