mirror of https://github.com/PCSX2/pcsx2.git
Timers: Fix up some timer behaviour
This commit is contained in:
parent
999f0cc84f
commit
3b63445f07
|
@ -220,11 +220,13 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, double framesPerSecond, u32 sca
|
||||||
const u64 Render = HalfFrame - Blank;
|
const u64 Render = HalfFrame - Blank;
|
||||||
const u64 GSBlank = Scanline * ((ntsc_hblank ? 3.5 : 3) + extra_scanlines); // GS VBlank/CSR Swap happens roughly 3.5(NTSC) and 3(PAL) Scanlines after VBlank Start
|
const u64 GSBlank = Scanline * ((ntsc_hblank ? 3.5 : 3) + extra_scanlines); // GS VBlank/CSR Swap happens roughly 3.5(NTSC) and 3(PAL) Scanlines after VBlank Start
|
||||||
|
|
||||||
// Important! The hRender/hBlank timers should be 50/50 for best results.
|
// Important! The hRender/hBlank timer ratio below is set according to PS2 tests.
|
||||||
// (this appears to be what the real EE's timing crystal does anyway)
|
// in EE Cycles taken from PAL system:
|
||||||
|
// 18876 cycles for hsync
|
||||||
u64 hBlank = Scanline / 2;
|
// 15796 cycles for hsync are low (render)
|
||||||
u64 hRender = Scanline - hBlank;
|
// Ratio: 83.68298368298368
|
||||||
|
u64 hRender = Scanline * 0.8368298368298368f;
|
||||||
|
u64 hBlank = Scanline - hRender;
|
||||||
|
|
||||||
if (!IsInterlacedVideoMode())
|
if (!IsInterlacedVideoMode())
|
||||||
{
|
{
|
||||||
|
@ -592,10 +594,9 @@ __fi void rcntUpdate_hScanline()
|
||||||
|
|
||||||
//iopEventAction = 1;
|
//iopEventAction = 1;
|
||||||
if (hsyncCounter.Mode == MODE_HBLANK)
|
if (hsyncCounter.Mode == MODE_HBLANK)
|
||||||
{ //HBLANK Start
|
{ //HBLANK End / HRENDER Begin
|
||||||
|
rcntEndGate(false, hsyncCounter.sCycle + hsyncCounter.CycleT);
|
||||||
rcntStartGate(false, hsyncCounter.sCycle + hsyncCounter.CycleT);
|
psxHBlankEnd();
|
||||||
psxHBlankStart();
|
|
||||||
|
|
||||||
// Setup the hRender's start and end cycle information:
|
// Setup the hRender's start and end cycle information:
|
||||||
hsyncCounter.sCycle += vSyncInfo.hBlank; // start (absolute cycle value)
|
hsyncCounter.sCycle += vSyncInfo.hBlank; // start (absolute cycle value)
|
||||||
|
@ -603,7 +604,7 @@ __fi void rcntUpdate_hScanline()
|
||||||
hsyncCounter.Mode = MODE_HRENDER;
|
hsyncCounter.Mode = MODE_HRENDER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //HBLANK END / HRENDER Begin
|
{ //HBLANK START / HRENDER End
|
||||||
if (!CSRreg.HSINT)
|
if (!CSRreg.HSINT)
|
||||||
{
|
{
|
||||||
CSRreg.HSINT = true;
|
CSRreg.HSINT = true;
|
||||||
|
@ -611,9 +612,8 @@ __fi void rcntUpdate_hScanline()
|
||||||
gsIrq();
|
gsIrq();
|
||||||
}
|
}
|
||||||
|
|
||||||
rcntEndGate(false, hsyncCounter.sCycle + hsyncCounter.CycleT);
|
rcntStartGate(false, hsyncCounter.sCycle + hsyncCounter.CycleT);
|
||||||
|
psxHBlankStart();
|
||||||
psxHBlankEnd();
|
|
||||||
|
|
||||||
// set up the hblank's start and end cycle information:
|
// set up the hblank's start and end cycle information:
|
||||||
hsyncCounter.sCycle += vSyncInfo.hRender; // start (absolute cycle value)
|
hsyncCounter.sCycle += vSyncInfo.hRender; // start (absolute cycle value)
|
||||||
|
@ -816,10 +816,14 @@ static __fi void rcntStartGate(bool isVblank, u32 sCycle)
|
||||||
break;
|
break;
|
||||||
case 0x1: // Reset on Vsync start
|
case 0x1: // Reset on Vsync start
|
||||||
case 0x3: // Reset on Vsync start and end
|
case 0x3: // Reset on Vsync start and end
|
||||||
|
{
|
||||||
counters[i].count = 0;
|
counters[i].count = 0;
|
||||||
counters[i].target &= 0xffff;
|
counters[i].target &= 0xffff;
|
||||||
|
const u32 change = (sCycle - counters[i].sCycleT) / counters[i].rate;
|
||||||
|
counters[i].sCycleT = sCycle - ((sCycle - counters[i].sCycleT) - (change * counters[i].rate));
|
||||||
EECNT_LOG("EE Counter[%d] %s StartGate Type%d, count = %x", i,
|
EECNT_LOG("EE Counter[%d] %s StartGate Type%d, count = %x", i,
|
||||||
isVblank ? "vblank" : "hblank", counters[i].mode.GateMode, counters[i].count);
|
isVblank ? "vblank" : "hblank", counters[i].mode.GateMode, counters[i].count);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -858,10 +862,14 @@ static __fi void rcntEndGate(bool isVblank, u32 sCycle)
|
||||||
|
|
||||||
case 0x2: // Reset on Vsync end
|
case 0x2: // Reset on Vsync end
|
||||||
case 0x3: // Reset on Vsync start and end
|
case 0x3: // Reset on Vsync start and end
|
||||||
|
{
|
||||||
EECNT_LOG("EE Counter[%d] %s EndGate Type%d, count = %x", i,
|
EECNT_LOG("EE Counter[%d] %s EndGate Type%d, count = %x", i,
|
||||||
isVblank ? "vblank" : "hblank", counters[i].mode.GateMode, counters[i].count);
|
isVblank ? "vblank" : "hblank", counters[i].mode.GateMode, counters[i].count);
|
||||||
counters[i].count = 0;
|
counters[i].count = 0;
|
||||||
counters[i].target &= 0xffff;
|
counters[i].target &= 0xffff;
|
||||||
|
const u32 change = (sCycle - counters[i].sCycleT) / counters[i].rate;
|
||||||
|
counters[i].sCycleT = sCycle - ((sCycle - counters[i].sCycleT) - (change * counters[i].rate));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -871,14 +879,11 @@ static __fi void rcntEndGate(bool isVblank, u32 sCycle)
|
||||||
|
|
||||||
static __fi void rcntWmode(int index, u32 value)
|
static __fi void rcntWmode(int index, u32 value)
|
||||||
{
|
{
|
||||||
if (rcntCanCount(index))
|
if (rcntCanCount(index) && counters[index].mode.ClockSource != 0x3)
|
||||||
{
|
{
|
||||||
if (counters[index].mode.ClockSource != 0x3)
|
const u32 change = (cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate;
|
||||||
{
|
counters[index].count += change;
|
||||||
const u32 change = (cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate;
|
counters[index].sCycleT += change * counters[index].rate;
|
||||||
counters[index].count += change;
|
|
||||||
counters[index].sCycleT += change * counters[index].rate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
counters[index].sCycleT = cpuRegs.cycle;
|
counters[index].sCycleT = cpuRegs.cycle;
|
||||||
|
@ -906,13 +911,10 @@ static __fi void rcntWcount(int index, u32 value)
|
||||||
EECNT_LOG("EE Counter[%d] writeCount = %x, oldcount=%x, target=%x", index, value, counters[index].count, counters[index].target);
|
EECNT_LOG("EE Counter[%d] writeCount = %x, oldcount=%x, target=%x", index, value, counters[index].count, counters[index].target);
|
||||||
|
|
||||||
// re-calculate the start cycle of the counter based on elapsed time since the last counter update:
|
// re-calculate the start cycle of the counter based on elapsed time since the last counter update:
|
||||||
if (rcntCanCount(index))
|
if (rcntCanCount(index) && counters[index].mode.ClockSource != 0x3)
|
||||||
{
|
{
|
||||||
if (counters[index].mode.ClockSource != 0x3)
|
const u32 change = (cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate;
|
||||||
{
|
counters[index].sCycleT += change * counters[index].rate;
|
||||||
const u32 change = (cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate;
|
|
||||||
counters[index].sCycleT += change * counters[index].rate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
counters[index].sCycleT = cpuRegs.cycle;
|
counters[index].sCycleT = cpuRegs.cycle;
|
||||||
|
@ -922,7 +924,7 @@ static __fi void rcntWcount(int index, u32 value)
|
||||||
// reset the target, and make sure we don't get a premature target.
|
// reset the target, and make sure we don't get a premature target.
|
||||||
counters[index].target &= 0xffff;
|
counters[index].target &= 0xffff;
|
||||||
|
|
||||||
if (counters[index].count > counters[index].target)
|
if (counters[index].count >= counters[index].target)
|
||||||
counters[index].target |= EECNT_FUTURE_TARGET;
|
counters[index].target |= EECNT_FUTURE_TARGET;
|
||||||
|
|
||||||
_rcntSet(index);
|
_rcntSet(index);
|
||||||
|
@ -938,15 +940,14 @@ static __fi void rcntWtarget(int index, u32 value)
|
||||||
// If the target is behind the current count, set it up so that the counter must
|
// If the target is behind the current count, set it up so that the counter must
|
||||||
// overflow first before the target fires:
|
// overflow first before the target fires:
|
||||||
|
|
||||||
if (rcntCanCount(index))
|
if (rcntCanCount(index) && counters[index].mode.ClockSource != 0x3)
|
||||||
{
|
{
|
||||||
if (counters[index].mode.ClockSource != 0x3)
|
const u32 change = (cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate;
|
||||||
{
|
counters[index].count += change;
|
||||||
const u32 change = (cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate;
|
counters[index].sCycleT += change * counters[index].rate;
|
||||||
counters[index].count += change;
|
|
||||||
counters[index].sCycleT += change * counters[index].rate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
counters[index].sCycleT = cpuRegs.cycle;
|
||||||
|
|
||||||
if (counters[index].target <= counters[index].count)
|
if (counters[index].target <= counters[index].count)
|
||||||
counters[index].target |= EECNT_FUTURE_TARGET;
|
counters[index].target |= EECNT_FUTURE_TARGET;
|
||||||
|
@ -972,7 +973,7 @@ __fi u32 rcntRcount(int index)
|
||||||
|
|
||||||
// Spams the Console.
|
// Spams the Console.
|
||||||
EECNT_LOG("EE Counter[%d] readCount32 = %x", index, ret);
|
EECNT_LOG("EE Counter[%d] readCount32 = %x", index, ret);
|
||||||
return ret;
|
return (u16)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint page>
|
template <uint page>
|
||||||
|
|
|
@ -524,7 +524,8 @@ void psxRcntWcount16(int index, u16 value)
|
||||||
const u32 change = (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate;
|
const u32 change = (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate;
|
||||||
psxCounters[index].sCycleT += change * psxCounters[index].rate;
|
psxCounters[index].sCycleT += change * psxCounters[index].rate;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
psxCounters[index].sCycleT = psxRegs.cycle;
|
||||||
psxCounters[index].count = value & 0xffff;
|
psxCounters[index].count = value & 0xffff;
|
||||||
|
|
||||||
psxCounters[index].target &= 0xffff;
|
psxCounters[index].target &= 0xffff;
|
||||||
|
@ -554,7 +555,8 @@ void psxRcntWcount32(int index, u32 value)
|
||||||
const u32 change = (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate;
|
const u32 change = (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate;
|
||||||
psxCounters[index].sCycleT += change * psxCounters[index].rate;
|
psxCounters[index].sCycleT += change * psxCounters[index].rate;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
psxCounters[index].sCycleT = psxRegs.cycle;
|
||||||
psxCounters[index].count = value;
|
psxCounters[index].count = value;
|
||||||
|
|
||||||
psxCounters[index].target &= 0xffffffff;
|
psxCounters[index].target &= 0xffffffff;
|
||||||
|
@ -752,6 +754,8 @@ void psxRcntWtarget16(int index, u32 value)
|
||||||
psxCounters[index].count += change;
|
psxCounters[index].count += change;
|
||||||
psxCounters[index].sCycleT += change * psxCounters[index].rate;
|
psxCounters[index].sCycleT += change * psxCounters[index].rate;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
psxCounters[index].sCycleT = psxRegs.cycle;
|
||||||
|
|
||||||
// protect the target from an early arrival.
|
// protect the target from an early arrival.
|
||||||
// if the target is behind the current count, then set the target overflow
|
// if the target is behind the current count, then set the target overflow
|
||||||
|
@ -786,6 +790,8 @@ void psxRcntWtarget32(int index, u32 value)
|
||||||
psxCounters[index].count += change;
|
psxCounters[index].count += change;
|
||||||
psxCounters[index].sCycleT += change * psxCounters[index].rate;
|
psxCounters[index].sCycleT += change * psxCounters[index].rate;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
psxCounters[index].sCycleT = psxRegs.cycle;
|
||||||
// protect the target from an early arrival.
|
// protect the target from an early arrival.
|
||||||
// if the target is behind the current count, then set the target overflow
|
// if the target is behind the current count, then set the target overflow
|
||||||
// flag, so that the target won't be active until after the next overflow.
|
// flag, so that the target won't be active until after the next overflow.
|
||||||
|
|
Loading…
Reference in New Issue