started working on Counters.c still needs more work

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@207 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
cottonvibes 2008-10-17 08:29:55 +00:00 committed by Gregory Hainaut
parent 8f3cb18ee5
commit 44bef02a14
2 changed files with 213 additions and 263 deletions

View File

@ -22,6 +22,7 @@
#include "Common.h"
#include "PsxCommon.h"
#include "GS.h"
#include "VU.h"
u64 profile_starttick = 0;
u64 profile_totalticks = 0;
@ -153,30 +154,23 @@ u64 GetCPUTicks()
}
void UpdateVSyncRate() {
if (Config.PsxType & 1) {
SysPrintf("PAL\n");
counters[4].Cycle = 227000;
//if(Config.PsxType & 2)counters[5].rate = PS2VBLANK_PAL_INT;
//else counters[5].rate = PS2VBLANK_PAL;
counters[5].Cycle = 720;
}
else {
SysPrintf("NTSC\n");
counters[4].Cycle = 227000;
//if(Config.PsxType & 2)counters[5].rate = PS2VBLANK_NTSC_INT;
//else counters[5].rate = PS2VBLANK_NTSC;
counters[5].Cycle = 720;
}
//if(Config.PsxType & 2)counters[5].rate = (Config.PsxType & 1) ? PS2VBLANK_PAL_INT : PS2VBLANK_NTSC_INT;
//else counters[5].rate = (Config.PsxType & 1) ? PS2VBLANK_PAL : PS2VBLANK_NTSC;
hblankend = 0;
counters[5].mode &= ~0x10000;
counters[4].sCycleT = cpuRegs.cycle;
counters[4].CycleT = HBLANKCNT(1);
counters[4].count = 1;
counters[5].CycleT = VBLANKCNT(1);
counters[5].count = 1;
counters[5].sCycleT = cpuRegs.cycle;
counters[5].mode &= ~0x10000;
counters[4].count = 1;
counters[5].count = 1;
counters[4].Cycle = 227000;
counters[5].Cycle = 720;
counters[4].CycleT = HBLANKCNT(1);
counters[5].CycleT = VBLANKCNT(1);
counters[4].sCycleT = cpuRegs.cycle;
counters[5].sCycleT = cpuRegs.cycle;
//rcntUpdTarget(4);
//counters[4].CycleT = counters[4].rate;
//rcntUpdTarget(5);
@ -189,11 +183,11 @@ void UpdateVSyncRate() {
}
else if (Config.PsxType & 1) {
iTicks = (GetTickFrequency() / 5000) * 100;
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): 50 fps\n");
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): 50 fps Pal\n");
}
else {
iTicks = (GetTickFrequency() / 5994) * 100;
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): 59.94 fps\n");
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): 59.94 fps NTSC\n");
}
rcntSet();
}
@ -228,99 +222,7 @@ extern void DummyExecuteVU1Block(void);
//static u32 lastWasSkip=0;
//extern u32 unpacktotal;
#include "VU.h"
void VSync()
{
if (counters[5].mode & 0x10000) { // VSync End (22 hsyncs)
// swap the vsync field
u32 newfield = (*(u32*)(PS2MEM_GS+0x1000)&0x2000) ? 0 : 0x2000;
*(u32*)(PS2MEM_GS+0x1000) = (*(u32*)(PS2MEM_GS+0x1000) & ~(1<<13)) | newfield;
iFrame++;
// wait until GS stops
if( CHECK_MULTIGS ) {
GSRingBufSimplePacket(GS_RINGTYPE_VSYNC, newfield, 0, 0);
}
else {
GSvsync(newfield);
// update here on single thread mode *OBSOLETE*
if( PAD1update != NULL ) PAD1update(0);
if( PAD2update != NULL ) PAD2update(1);
}
counters[5].mode&= ~0x10000;
hwIntcIrq(3);
psxVSyncEnd();
if(gates)rcntEndGate(0x8);
SysUpdate();
// used to limit frames
switch(CHECK_FRAMELIMIT) {
case PCSX2_FRAMELIMIT_LIMIT:
FrameLimiter();
break;
case PCSX2_FRAMELIMIT_SKIP:
case PCSX2_FRAMELIMIT_VUSKIP: //Skips a sequence of consecutive frames after a sequence of rendered frames
{
// This is the least number of consecutive frames we will render w/o skipping
#define noSkipFrames (Config.CustomConsecutiveFrames>0) ? Config.CustomConsecutiveFrames : 2
// This is the number of consecutive frames we will skip
#define yesSkipFrames (Config.CustomConsecutiveSkip>0) ? Config.CustomConsecutiveSkip : 2
static u8 bOkayToSkip = 0;
static u8 bKeepSkipping = 0;
static u64 uLastTime = 0;
// This is some Extra Time to add to our Expected Time to compensate for lack of precision.
#define extraTimeBuffer 0
// If uDeltaTime is less than this value, then we can frameskip. (45 & 54 FPS is 90% of fullspeed for Pal & NTSC respectively, the default is to only skip when slower than 90%)
u64 uExpectedTime = (Config.CustomFrameSkip>0) ? (GetTickFrequency()/Config.CustomFrameSkip + extraTimeBuffer) : ((Config.PsxType&1) ? (GetTickFrequency()/45 + extraTimeBuffer) : (GetTickFrequency()/54 + extraTimeBuffer));
// This is used for the framelimiter; The user can set a custom FPS limit, if none is specified, used default FPS limit (50fps or 60fps).
//u64 uLimiterExpectedTime = (Config.CustomFps>0) ? (GetTickFrequency()/Config.CustomFps + extraTimeBuffer) : ((Config.PsxType&1) ? (GetTickFrequency()/50 + extraTimeBuffer) : (GetTickFrequency()/60 + extraTimeBuffer));
u64 uCurTime = GetCPUTicks();
u64 uDeltaTime = uCurTime - uLastTime;
// Don't skip the Very First Frame PCSX2 renders. (This line might not be needed, but was included incase it breaks something.)
if (uDeltaTime == uCurTime) uDeltaTime = 0;
if (bOkayToSkip == 0) // If we're done rendering our consecutive frames, its okay to skip.
{
if (uDeltaTime > uExpectedTime) // Only skip if running slow.
{
//first freeze GS regs THEN send dummy packet
if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 1, 0, 0);
else GSsetFrameSkip(1);
if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP )
Cpu->ExecuteVU1Block = DummyExecuteVU1Block;
bOkayToSkip = noSkipFrames;
bKeepSkipping = yesSkipFrames;
}
}
else if (bOkayToSkip == noSkipFrames) // If we skipped last frame, unfreeze the GS regs
{
if (bKeepSkipping <= 1) {
//first set VU1 to enabled THEN unfreeze GS regs
if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP )
Cpu->ExecuteVU1Block = s_prevExecuteVU1Block;
if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 0, 0, 0);
else GSsetFrameSkip(0);
bOkayToSkip--;
}
else {bKeepSkipping--;}
}
else {bOkayToSkip--;}
//Frame Limit so we don't go over the FPS limit
FrameLimiter();
uLastTime = GetCPUTicks();
break;
}
}
} else { // VSync Start (240 hsyncs)
void vSyncDebugStuff() {
#ifdef EE_PROFILING
if( (iFrame%20) == 0 ) {
SysPrintf("Profiled Cycles at %d frames %d\n", iFrame, profile_totalticks);
@ -399,100 +301,186 @@ void VSync()
}
}
#endif
}
//SysPrintf("ctrs: %d %d %d %d\n", g_nCounters[0], g_nCounters[1], g_nCounters[2], g_nCounters[3]);
//SysPrintf("vif: %d\n", (((LARGE_INTEGER*)g_nCounters)->QuadPart * 1000000) / lfreq.QuadPart);
//memset(g_nCounters, 0, 16);
__forceinline void frameLimit()
{
switch(CHECK_FRAMELIMIT) {
case PCSX2_FRAMELIMIT_LIMIT:
FrameLimiter();
break;
counters[5].mode|= 0x10000;
if ((CSRw & 0x8)) GSCSRr|= 0x8;
if (!(GSIMR&0x800)) gsIrq();
case PCSX2_FRAMELIMIT_SKIP:
case PCSX2_FRAMELIMIT_VUSKIP: //Skips a sequence of consecutive frames after a sequence of rendered frames
{
// This is the least number of consecutive frames we will render w/o skipping
#define noSkipFrames (Config.CustomConsecutiveFrames>0) ? Config.CustomConsecutiveFrames : 2
// This is the number of consecutive frames we will skip
#define yesSkipFrames (Config.CustomConsecutiveSkip>0) ? Config.CustomConsecutiveSkip : 2
static u8 bOkayToSkip = 0;
static u8 bKeepSkipping = 0;
static u64 uLastTime = 0;
hwIntcIrq(2);
psxVSyncStart();
if(Config.Patch) applypatch(1);
if(gates)rcntStartGate(0x8);
// This is some Extra Time to add to our Expected Time to compensate for lack of precision.
#define extraTimeBuffer 0
// If uDeltaTime is less than this value, then we can frameskip. (45 & 54 FPS is 90% of fullspeed for Pal & NTSC respectively, the default is to only skip when slower than 90%)
u64 uExpectedTime = (Config.CustomFrameSkip>0) ? (GetTickFrequency()/Config.CustomFrameSkip + extraTimeBuffer) : ((Config.PsxType&1) ? (GetTickFrequency()/45 + extraTimeBuffer) : (GetTickFrequency()/54 + extraTimeBuffer));
// This is used for the framelimiter; The user can set a custom FPS limit, if none is specified, used default FPS limit (50fps or 60fps).
//u64 uLimiterExpectedTime = (Config.CustomFps>0) ? (GetTickFrequency()/Config.CustomFps + extraTimeBuffer) : ((Config.PsxType&1) ? (GetTickFrequency()/50 + extraTimeBuffer) : (GetTickFrequency()/60 + extraTimeBuffer));
u64 uCurTime = GetCPUTicks();
u64 uDeltaTime = uCurTime - uLastTime;
//__Log("%u %u 0\n", cpuRegs.cycle-s_lastvsync[1], timeGetTime()-s_lastvsync[0]);
//s_lastvsync[0] = timeGetTime();
//s_lastvsync[1] = cpuRegs.cycle;
// Don't skip the Very First Frame PCSX2 renders. (This line might not be needed, but was included incase it breaks something.)
if (uDeltaTime == uCurTime) uDeltaTime = 0;
if (bOkayToSkip == 0) // If we're done rendering our consecutive frames, its okay to skip.
{
if (uDeltaTime > uExpectedTime) // Only skip if running slow.
{
//first freeze GS regs THEN send dummy packet
if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 1, 0, 0);
else GSsetFrameSkip(1);
if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP )
Cpu->ExecuteVU1Block = DummyExecuteVU1Block;
bOkayToSkip = noSkipFrames;
bKeepSkipping = yesSkipFrames;
}
}
else if (bOkayToSkip == noSkipFrames) // If we skipped last frame, unfreeze the GS regs
{
if (bKeepSkipping <= 1) {
//first set VU1 to enabled THEN unfreeze GS regs
if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP )
Cpu->ExecuteVU1Block = s_prevExecuteVU1Block;
if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 0, 0, 0);
else GSsetFrameSkip(0);
bOkayToSkip--;
}
else {bKeepSkipping--;}
}
else {bOkayToSkip--;}
//Frame Limit so we don't go over the FPS limit
FrameLimiter();
uLastTime = GetCPUTicks();
break;
}
}
}
void VSyncStart() // VSync Start (240 hsyncs)
{
vSyncDebugStuff(); // EE Profiling and Debug code
if ((CSRw & 0x8)) GSCSRr|= 0x8;
if (!(GSIMR&0x800)) gsIrq(); //GS Irq
hwIntcIrq(2); // HW Irq
psxVSyncStart(); // psxCounters vSync Start
if (Config.Patch) applypatch(1); // Apply patches (ToDo: clean up patch code)
if (gates) rcntStartGate(0x8); // Counters Start Gate code
counters[5].mode ^= 0x10000; // Alternate vSync Start/End
}
void VSyncEnd() // VSync End (22 hsyncs)
{
iFrame++;
*(u32*)(PS2MEM_GS+0x1000) ^= 0x2000; // swap the vsync field
// wait until GS stops
if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_VSYNC, (*(u32*)(PS2MEM_GS+0x1000)&0x2000), 0, 0);
else {
GSvsync((*(u32*)(PS2MEM_GS+0x1000)&0x2000));
// update here on single thread mode *OBSOLETE*
if( PAD1update != NULL ) PAD1update(0);
if( PAD2update != NULL ) PAD2update(1);
}
hwIntcIrq(3); // HW Irq
psxVSyncEnd(); // psxCounters vSync End
if (gates) rcntEndGate(0x8); // Counters End Gate Code
SysUpdate(); // check for and handle keyevents
frameLimit(); // limit FPS (also handles frameskip and VUskip)
counters[5].mode ^= 0x10000; // Alternate vSync Start/End
}
void rcntUpdate()
{
int i;
u32 change = 0;
for (i=0; i<=3; i++) {
if(gates & (1<<i) ) {
//SysPrintf("Stopped accidental update of ee counter %x when using a gate\n", i);
continue;
}
if ( gates & (1<<i) ) continue;
if ((counters[i].mode & 0x80) && (counters[i].mode & 0x3) != 0x3) {
change = cpuRegs.cycle - counters[i].sCycleT;
//counters[i].count += (cpuRegs.cycle - counters[i].sCycleT) / counters[i].rate;
//counters[i].sCycleT = cpuRegs.cycle;
u32 change = cpuRegs.cycle - counters[i].sCycleT;
counters[i].count += (int)(change / counters[i].rate);
change -= (change / counters[i].rate) * counters[i].rate;
counters[i].sCycleT = cpuRegs.cycle - change;
}
else change = 0;
else counters[i].sCycleT = cpuRegs.cycle;
}
counters[i].sCycleT = cpuRegs.cycle - change;
//if(change > 0) SysPrintf("Change saved on %x = %x\n", i, change);
}
if ((u32)(cpuRegs.cycle - counters[4].sCycleT) >= (u32)counters[4].CycleT && hblankend == 1) {
if ((u32)(cpuRegs.cycle - counters[4].sCycleT) >= (u32)counters[4].CycleT) {
if (CSRw & 0x4) GSCSRr |= 4; // signal
if (!(GSIMR&0x400)) gsIrq();
if (gates) rcntEndGate(0);
if (psxhblankgate) psxCheckEndGate(0);
hblankend = 0;
counters[4].CycleT = HBLANKCNT(counters[4].count);
}
else if ((u32)(cpuRegs.cycle - counters[4].sCycleT) >= (u32)counters[4].CycleT) {
if(counters[4].count >= counters[4].Cycle) {
//SysPrintf("%x of %x hblanks reorder in %x cycles cpuRegs.cycle = %x\n", counters[4].count, counters[4].Cycle, cpuRegs.cycle - counters[4].sCycleT, cpuRegs.cycle);
counters[4].sCycleT += HBLANKCNT(counters[4].Cycle);
counters[4].count -= counters[4].Cycle;
}
//counters[4].sCycleT += HBLANKCNT(1);
counters[4].count++;
if (hblankend == 1) {
if (CSRw & 0x4) GSCSRr |= 4; // signal
if (!(GSIMR&0x400)) gsIrq();
if (gates) rcntEndGate(0);
if (psxhblankgate) psxCheckEndGate(0);
hblankend = 0;
counters[4].CycleT = HBLANKCNT(counters[4].count) - (HBLANKCNT(0.5));
rcntStartGate(0);
psxCheckStartGate(0);
hblankend = 1;
//if(cpuRegs.cycle > 0xffff0000 || cpuRegs.cycle < 0x1000
//SysPrintf("%x hsync done in %x cycles cpuRegs.cycle = %x next will happen on %x\n", counters[4].count, counters[4].CycleT, cpuRegs.cycle, (u32)(counters[4].sCycleT + counters[4].CycleT));
counters[4].CycleT = HBLANKCNT(counters[4].count);
}
else {
if(counters[4].count >= counters[4].Cycle) {
//SysPrintf("%x of %x hblanks reorder in %x cycles cpuRegs.cycle = %x\n", counters[4].count, counters[4].Cycle, cpuRegs.cycle - counters[4].sCycleT, cpuRegs.cycle);
counters[4].sCycleT += HBLANKCNT(counters[4].Cycle);
counters[4].count -= counters[4].Cycle;
}
//counters[4].sCycleT += HBLANKCNT(1);
counters[4].count++;
counters[4].CycleT = HBLANKCNT(counters[4].count) - (HBLANKCNT(0.5));
rcntStartGate(0);
psxCheckStartGate(0);
hblankend = 1;
//SysPrintf("%x hsync done in %x cycles cpuRegs.cycle = %x next will happen on %x\n", counters[4].count, counters[4].CycleT, cpuRegs.cycle, (u32)(counters[4].sCycleT + counters[4].CycleT));
}
}
if((counters[5].mode & 0x10000)) {
if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT){
if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT) {
if (counters[5].mode & 0x10000) {
//counters[5].sCycleT = cpuRegs.cycle;
counters[5].CycleT = VBLANKCNT(counters[5].count);
VSync();
VSyncEnd();
}
}
else if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT) {
if(counters[5].count >= counters[5].Cycle) {
//SysPrintf("reset %x of %x frames done in %x cycles cpuRegs.cycle = %x\n", counters[5].count, counters[5].Cycle, cpuRegs.cycle - counters[5].sCycleT, cpuRegs.cycle);
counters[5].sCycleT += VBLANKCNT(counters[5].Cycle);
counters[5].count -= counters[5].Cycle;
else {
if(counters[5].count >= counters[5].Cycle) {
//SysPrintf("reset %x of %x frames done in %x cycles cpuRegs.cycle = %x\n", counters[5].count, counters[5].Cycle, cpuRegs.cycle - counters[5].sCycleT, cpuRegs.cycle);
counters[5].sCycleT += VBLANKCNT(counters[5].Cycle);
counters[5].count -= counters[5].Cycle;
}
counters[5].count++;
//counters[5].sCycleT += VBLANKCNT(1); //this line brings back magna carta loading animation, but breaks vsyncs >< (rama)
counters[5].CycleT = VBLANKCNT(counters[5].count) - (VBLANKCNT(1)/2);
//SysPrintf("%x frames done in %x cycles cpuRegs.cycle = %x cycletdiff %x\n", counters[5].Cycle, counters[5].sCycleT, cpuRegs.cycle, (counters[5].CycleT - VBLANKCNT(1)) - (cpuRegs.cycle - counters[5].sCycleT));
VSyncStart();
}
counters[5].count++;
//counters[5].sCycleT += VBLANKCNT(1); //this line brings back magna carta loading animation, but breaks vsyncs >< (rama)
counters[5].CycleT = VBLANKCNT(counters[5].count) - (VBLANKCNT(1)/2);
//SysPrintf("%x frames done in %x cycles cpuRegs.cycle = %x cycletdiff %x\n", counters[5].Cycle, counters[5].sCycleT, cpuRegs.cycle, (counters[5].CycleT - VBLANKCNT(1)) - (cpuRegs.cycle - counters[5].sCycleT));
VSync();
}
for (i=0; i<=3; i++) {
if (!(counters[i].mode & 0x80)) continue; // Stopped
if ((s64)(counters[i].target - counters[i].count) <= 0 /*&& (counters[i].target & 0xffff) > 0*/) { // Target interrupt
if (counters[i].count >= counters[i].target) { // Target interrupt
//if((counters[i].target > 0xffff)) {
//SysPrintf("EE Correcting target %x after reset on target\n", i);
@ -502,10 +490,11 @@ void rcntUpdate()
if(counters[i].mode & 0x100 ) {
EECNT_LOG("EE counter %d target reached mode %x count %x target %x\n", i, counters[i].mode, counters[i].count, counters[i].target);
counters[i].mode|= 0x0400; // Target flag
counters[i].mode|= 0x0400; // Equal Target flag
hwIntcIrq(counters[i].interrupt);
if (counters[i].mode & 0x40) { //The PS2 only resets if the interrupt is enabled - Tested on PS2
//counters[i].count = 0;
counters[i].count -= counters[i].target; // Reset on target
}
else counters[i].target += 0x10000000;
@ -521,11 +510,9 @@ void rcntUpdate()
hwIntcIrq(counters[i].interrupt);
//SysPrintf("counter[%d] overflow interrupt (%x)\n", i, cpuRegs.cycle);
}
//counters[i].count = 0;
counters[i].count -= 0x10000;
//if(counters[i].target > 0xffff) {
//SysPrintf("EE %x Correcting target on overflow\n", i);
counters[i].target &= 0xffff;
//}
counters[i].target &= 0xffff;
}
}
@ -533,63 +520,41 @@ void rcntUpdate()
}
void rcntWcount(int index, u32 value) {
u32 change = 0;
EECNT_LOG("EE count write %d count %x with %x target %x eecycle %x\n", index, counters[index].count, value, counters[index].target, cpuRegs.eCycle);
counters[index].count = value & 0xffff;
//if(counters[index].target > 0xffff) {
//SysPrintf("EE Counter %x count write, target > 0xffff\n", index);
counters[index].target &= 0xffff;
//}
counters[index].target &= 0xffff;
//rcntUpd(index);
if((counters[index].mode & 0x3) != 0x3) {
change = cpuRegs.cycle - counters[index].sCycleT;
//counters[index].sCycleT = cpuRegs.cycle;
u32 change = cpuRegs.cycle - counters[index].sCycleT;
change -= (change / counters[index].rate) * counters[index].rate;
counters[index].sCycleT = cpuRegs.cycle - change;
}
/* else {
SysPrintf("EE Counter %x count write %x\n", index, value);
}*/
rcntSet();
}
void rcntWmode(int index, u32 value)
{
u32 change = 0;
if (value & 0xc00) { //Clear status flags, the ps2 only clears what is given in the value
counters[index].mode &= ~(value & 0xc00);
}
if(counters[index].mode & 0x80) {
if((counters[index].mode & 0x3) != 0x3){
change = cpuRegs.cycle - counters[index].sCycleT;
if((counters[index].mode & 0x3) != 0x3) {
//counters[index].count += (cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate;
//counters[index].sCycleT = cpuRegs.cycle;
u32 change = cpuRegs.cycle - counters[index].sCycleT;
counters[index].count += (int)(change / counters[index].rate);
change -= (change / counters[index].rate) * counters[index].rate;
counters[index].sCycleT = cpuRegs.cycle - change;
}
//if(change != 0) SysPrintf("Weee\n");
//counters[index].sCycleT = cpuRegs.cycle - ((cpuRegs.cycle - counters[index].sCycleT) % counters[index].rate);
#ifdef PCSX2_DEVBUILD
if(!(value & 0x80)) SysPrintf("Stopping\n");
#endif
}
else {
#ifdef PCSX2_DEVBUILD
SysPrintf("Counter %d not running c%x s%x c%x\n", index, counters[index].count, counters[index].sCycleT, cpuRegs.cycle);
if(value & 0x80) SysPrintf("Starting %d, v%x\n", index, value);
#endif
counters[index].sCycleT = cpuRegs.cycle;
}
else counters[index].sCycleT = cpuRegs.cycle;
//if((value & 0x80) && !(counters[index].mode & 0x80)) rcntUpd(index); //Counter wasnt started, so set the start cycle
counters[index].mode &= ~(value & 0xc00); //Clear status flags, the ps2 only clears what is given in the value
counters[index].mode = (counters[index].mode & 0xc00) | (value & 0x3ff);
EECNT_LOG("EE counter set %d mode %x count %x\n", index, counters[index].mode, rcntCycle(index));
/*if((value & 0x3) && (counters[index].mode & 0x3) != 0x3){
//SysPrintf("Syncing %d with HBLANK clock\n", index);
counters[index].CycleT = counters[4].CycleT;
}*/
switch (value & 0x3) { //Clock rate divisers *2, they use BUSCLK speed not PS2CLK
case 0: counters[index].rate = 2; break;
case 1: counters[index].rate = 32; break;
@ -603,10 +568,9 @@ void rcntWmode(int index, u32 value)
//counters[index].mode &= ~0x80;
}
else if (counters[index].mode & 0x4) {
// SysPrintf("Gate enable on counter %x mode %x\n", index, counters[index].mode);
gates |= 1<<index;
counters[index].mode &= ~0x80;
rcntReset(index);
gates |= (1<<index);
counters[index].mode &= ~0x80;
rcntReset(index);
}
else gates &= ~(1<<index);
@ -621,38 +585,29 @@ void rcntWmode(int index, u32 value)
void rcntStartGate(unsigned int mode){
int i;
if(mode == 0){
for(i = 0; i < 4; i++){ //Update counters using the hblank as the clock
if((counters[i].mode & 0x83) == 0x83) counters[i].count++;
}
}
for (i=0; i <=3; i++) { //Gates for counters
for(i=0; i <=3; i++){ //Gates for counters
if(!(gates & (1<<i))) continue;
if ((mode == 0) && ((counters[i].mode & 0x83) == 0x83)) counters[i].count++; //Update counters using the hblank as the clock
if (!(gates & (1<<i))) continue;
if ((counters[i].mode & 0x8) != mode) continue;
//SysPrintf("Gate %d mode %d Start\n", i, (counters[i].mode & 0x30) >> 4);
switch((counters[i].mode & 0x30) >> 4) {
case 0x0: //Count When Signal is low (off)
switch (counters[i].mode & 0x30) {
case 0x00: //Count When Signal is low (off)
counters[i].count = rcntRcount(i);
rcntUpd(i);
counters[i].mode &= ~0x80;
break;
case 0x1: //Reset and start counting on Vsync start
counters[i].mode |= 0x80;
rcntReset(i);
counters[i].target &= 0xffff;
break;
case 0x2: //Reset and start counting on Vsync end
case 0x20: //Reset and start counting on Vsync end
//Do Nothing
break;
case 0x3: //Reset and start counting on Vsync start and end
case 0x10: //Reset and start counting on Vsync start
case 0x30: //Reset and start counting on Vsync start and end
counters[i].mode |= 0x80;
rcntReset(i);
counters[i].target &= 0xffff;
break;
default:
SysPrintf("EE Start Counter %x Gate error\n", i);
break;
}
}
}
@ -660,30 +615,23 @@ void rcntEndGate(unsigned int mode) {
int i;
for(i=0; i <=3; i++) { //Gates for counters
if(!(gates & (1<<i))) continue;
if (!(gates & (1<<i))) continue;
if ((counters[i].mode & 0x8) != mode) continue;
//SysPrintf("Gate %d mode %d End\n", i, (counters[i].mode & 0x30) >> 4);
switch((counters[i].mode & 0x30) >> 4){
case 0x0: //Count When Signal is low (off)
switch (counters[i].mode & 0x30) {
case 0x00: //Count When Signal is low (off)
rcntUpd(i);
counters[i].mode |= 0x80;
break;
case 0x1: //Reset and start counting on Vsync start
case 0x10: //Reset and start counting on Vsync start
//Do Nothing
break;
case 0x2: //Reset and start counting on Vsync end
counters[i].mode |= 0x80;
rcntReset(i);
counters[i].target &= 0xffff;
break;
case 0x3: //Reset and start counting on Vsync start and end
case 0x20: //Reset and start counting on Vsync end
case 0x30: //Reset and start counting on Vsync start and end
counters[i].mode |= 0x80;
rcntReset(i);
counters[i].target &= 0xffff;
break;
default:
SysPrintf("EE Start Counter %x Gate error\n", i);
break;
}
}
}
@ -691,6 +639,7 @@ void rcntWtarget(int index, u32 value) {
EECNT_LOG("EE target write %d target %x value %x\n", index, counters[index].target, value);
counters[index].target = value & 0xffff;
if (counters[index].target <= rcntCycle(index)/* && counters[index].target != 0*/) {
//SysPrintf("EE Saving target %d from early trigger, target = %x, count = %x\n", index, counters[index].target, rcntCycle(index));
counters[index].target += 0x10000000;
@ -700,7 +649,8 @@ void rcntWtarget(int index, u32 value) {
void rcntWhold(int index, u32 value) {
EECNT_LOG("EE hold write %d value %x\n", index, value);
counters[index].hold = value;
if (value & 0xffff0000) SysPrintf("rcntWhold: bad value\n");
counters[index].hold = value & 0xffff;
}
u32 rcntRcount(int index) {
@ -717,9 +667,9 @@ u32 rcntRcount(int index) {
u32 rcntCycle(int index) {
if ((counters[index].mode & 0x80))
if ((counters[index].mode & 0x80))
return (u32)counters[index].count + (int)((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate);
else
else
return (u32)counters[index].count;
}

View File

@ -37,8 +37,8 @@ void rcntWcount(int index, u32 value);
void rcntWmode(int index, u32 value);
void rcntWtarget(int index, u32 value);
void rcntWhold(int index, u32 value);
u32 rcntRcount(int index);
u32 rcntCycle(int index);
u32 rcntRcount(int index);
u32 rcntCycle(int index);
int rcntFreeze(gzFile f, int Mode);
void UpdateVSyncRate();