mirror of https://github.com/PCSX2/pcsx2.git
reverted counters.c to official SVN's code for now (my code was crashing Devil May Cry for some reason...)
git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@243 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
parent
7ef953567d
commit
eaf15db0fe
596
pcsx2/Counters.c
596
pcsx2/Counters.c
|
@ -22,18 +22,22 @@
|
|||
#include "Common.h"
|
||||
#include "PsxCommon.h"
|
||||
#include "GS.h"
|
||||
#include "VU.h"
|
||||
|
||||
u64 profile_starttick = 0;
|
||||
u64 profile_totalticks = 0;
|
||||
|
||||
int gates = 0;
|
||||
extern u8 psxhblankgate;
|
||||
int hblankend = 0;
|
||||
Counter counters[6];
|
||||
u32 nextCounter, nextsCounter;
|
||||
static void (*s_prevExecuteVU1Block)() = NULL;
|
||||
LARGE_INTEGER lfreq;
|
||||
|
||||
// its so it doesnt keep triggering an interrupt once its reached its target
|
||||
// if it doesnt reset the counter it needs stopping
|
||||
u32 eecntmask = 0;
|
||||
|
||||
void rcntUpdTarget(int index) {
|
||||
counters[index].sCycleT = cpuRegs.cycle;
|
||||
}
|
||||
|
@ -45,6 +49,7 @@ void rcntUpd(int index) {
|
|||
|
||||
void rcntReset(int index) {
|
||||
counters[index].count = 0;
|
||||
//counters[index].mode&= ~0x00400C00;
|
||||
rcntUpd(index);
|
||||
}
|
||||
|
||||
|
@ -52,7 +57,7 @@ void rcntSet() {
|
|||
u32 c;
|
||||
int i;
|
||||
|
||||
nextCounter = HBLANK_TIME_;
|
||||
nextCounter = 0xffffffff;
|
||||
nextsCounter = cpuRegs.cycle;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
@ -67,15 +72,13 @@ void rcntSet() {
|
|||
}
|
||||
|
||||
//Calculate HBlank
|
||||
/*
|
||||
if (counters[4].mode & MODE_HBLANK) { //hBlank
|
||||
if (Config.PsxType&1) { if (HBLANK_TIME_PAL < nextCounter) nextCounter = HBLANK_TIME_PAL; }
|
||||
else if (HBLANK_TIME_NTSC < nextCounter) nextCounter = HBLANK_TIME_NTSC;
|
||||
}
|
||||
else { //not hBlank (drawing part of the scanline)
|
||||
if (Config.PsxType&1) { if (HRENDER_TIME_PAL < nextCounter) nextCounter = HRENDER_TIME_PAL; }
|
||||
else if (HRENDER_TIME_NTSC < nextCounter) nextCounter = HRENDER_TIME_NTSC;
|
||||
}*/
|
||||
c = counters[4].CycleT - (cpuRegs.cycle - counters[4].sCycleT);
|
||||
if (c < nextCounter) nextCounter = c;
|
||||
//if(nextCounter > 0x1000) SysPrintf("Nextcounter %x HBlank %x VBlank %x\n", nextCounter, c, counters[5].CycleT - (cpuRegs.cycle - counters[5].sCycleT));
|
||||
|
||||
//Calculate VBlank
|
||||
c = counters[5].CycleT - (cpuRegs.cycle - counters[5].sCycleT);
|
||||
if (c < nextCounter) nextCounter = c;
|
||||
}
|
||||
|
||||
void rcntInit() {
|
||||
|
@ -92,8 +95,19 @@ void rcntInit() {
|
|||
counters[2].interrupt = 11;
|
||||
counters[3].interrupt = 12;
|
||||
|
||||
UpdateVSyncRate();
|
||||
counters[4].mode = 0x3c0; // The VSync counter mode
|
||||
counters[5].mode = 0x3c0;
|
||||
|
||||
UpdateVSyncRate();
|
||||
/*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;*/
|
||||
|
||||
#ifdef _WIN32
|
||||
QueryPerformanceFrequency(&lfreq);
|
||||
#endif
|
||||
|
@ -139,24 +153,47 @@ 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;
|
||||
}
|
||||
|
||||
counters[4].mode = MODE_HRENDER; // Counter 4 takes care of scanlines, so set the mode to HRENDER (drawing part of scanline)
|
||||
counters[4].sCycle = cpuRegs.cycle; // Update Counter 4's Start Cycle to match CPU's cycle
|
||||
|
||||
counters[5].mode = MODE_VRENDER; // Counter 5 takes care of vSync/vBlanks
|
||||
counters[5].sCycle = cpuRegs.cycle; // Update Counter 5's Start Cycle to match CPU's cycle
|
||||
|
||||
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;
|
||||
|
||||
//rcntUpdTarget(4);
|
||||
//counters[4].CycleT = counters[4].rate;
|
||||
//rcntUpdTarget(5);
|
||||
//counters[5].CycleT = counters[5].rate;
|
||||
//counters[5].Cycle = PS2VBLANKEND;
|
||||
|
||||
if (Config.CustomFps > 0) {
|
||||
iTicks = GetTickFrequency() / Config.CustomFps;
|
||||
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): %d fps\n", Config.CustomFps);
|
||||
}
|
||||
else if (Config.PsxType & 1) {
|
||||
iTicks = (GetTickFrequency() / 5000) * 100;
|
||||
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): 50 fps Pal\n");
|
||||
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): 50 fps\n");
|
||||
}
|
||||
else {
|
||||
iTicks = (GetTickFrequency() / 5994) * 100;
|
||||
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): 59.94 fps NTSC\n");
|
||||
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): 59.94 fps\n");
|
||||
}
|
||||
rcntSet();
|
||||
}
|
||||
|
@ -172,12 +209,12 @@ void FrameLimiter()
|
|||
|
||||
if (iEnd>=iExpectedEnd) {
|
||||
u64 diff = iEnd-iExpectedEnd;
|
||||
if ((diff>>3)>iTicks) iExpectedEnd=iEnd;
|
||||
if((diff>>3)>iTicks) iExpectedEnd=iEnd;
|
||||
}
|
||||
else do {
|
||||
_TIMESLICE();
|
||||
Sleep(1);
|
||||
iEnd = GetCPUTicks();
|
||||
} while (iEnd<iExpectedEnd);
|
||||
} while(iEnd<iExpectedEnd);
|
||||
|
||||
iStart = iExpectedEnd; //remember the expected value frame. improves smoothness
|
||||
}
|
||||
|
@ -191,7 +228,99 @@ extern void DummyExecuteVU1Block(void);
|
|||
//static u32 lastWasSkip=0;
|
||||
//extern u32 unpacktotal;
|
||||
|
||||
void vSyncDebugStuff() {
|
||||
#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);
|
||||
psxVBlankEnd();
|
||||
|
||||
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)
|
||||
#ifdef EE_PROFILING
|
||||
if( (iFrame%20) == 0 ) {
|
||||
SysPrintf("Profiled Cycles at %d frames %d\n", iFrame, profile_totalticks);
|
||||
|
@ -270,287 +399,218 @@ void vSyncDebugStuff() {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void frameLimit()
|
||||
{
|
||||
switch(CHECK_FRAMELIMIT) {
|
||||
case PCSX2_FRAMELIMIT_LIMIT:
|
||||
FrameLimiter();
|
||||
break;
|
||||
//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);
|
||||
|
||||
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;
|
||||
counters[5].mode|= 0x10000;
|
||||
if ((CSRw & 0x8)) GSCSRr|= 0x8;
|
||||
if (!(GSIMR&0x800)) gsIrq();
|
||||
|
||||
// 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;
|
||||
hwIntcIrq(2);
|
||||
psxVBlankStart();
|
||||
|
||||
if(Config.Patch) applypatch(1);
|
||||
if(gates)rcntStartGate(0x8);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void VBlankStart()
|
||||
{
|
||||
psxVBlankStart(); // psxCounters vBlank Start
|
||||
if (gates) rcntStartGate(0x8); // Counters Start Gate code
|
||||
}
|
||||
|
||||
__forceinline void VBlankEnd()
|
||||
{
|
||||
psxVBlankEnd(); // psxCounters vBlank End
|
||||
if (gates) rcntEndGate(0x8); // Counters End Gate Code
|
||||
SysUpdate(); // check for and handle keyevents
|
||||
}
|
||||
|
||||
__forceinline 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
|
||||
VBlankStart();
|
||||
if (Config.Patch) applypatch(1); // Apply patches (ToDo: clean up patch code)
|
||||
}
|
||||
|
||||
__forceinline 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
|
||||
VBlankEnd();
|
||||
frameLimit(); // limit FPS (also handles frameskip and VUskip)
|
||||
}
|
||||
|
||||
#define hScanlineOptimization(diff, compareValue, incrementCounters) { \
|
||||
if (diff >= compareValue) { \
|
||||
SysPrintf("Counters Optimization\n"); \
|
||||
if (incrementCounters) { \
|
||||
u32 increment = (diff / compareValue); \
|
||||
/* if counter's count increases on hblank gate's off signal OR if counter increases every hblank, THEN add to the counter */ \
|
||||
if ( (!(counters[0].mode & 0x30) && (gates & (1<<0))) || (((counters[0].mode & 0x83) == 0x83) && !(gates & (1<<0))) ) counters[0].count += (increment * HBLANK_COUNTER_SPEED); \
|
||||
if ( (!(counters[1].mode & 0x30) && (gates & (1<<1))) || (((counters[1].mode & 0x83) == 0x83) && !(gates & (1<<1))) ) counters[1].count += (increment * HBLANK_COUNTER_SPEED); \
|
||||
if ( (!(counters[2].mode & 0x30) && (gates & (1<<2))) || (((counters[2].mode & 0x83) == 0x83) && !(gates & (1<<2))) ) counters[2].count += (increment * HBLANK_COUNTER_SPEED); \
|
||||
if ( (!(counters[3].mode & 0x30) && (gates & (1<<3))) || (((counters[3].mode & 0x83) == 0x83) && !(gates & (1<<3))) ) counters[3].count += (increment * HBLANK_COUNTER_SPEED); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
__forceinline void hScanline()
|
||||
{
|
||||
u32 difference = (cpuRegs.cycle - counters[4].sCycle);
|
||||
|
||||
if (counters[4].mode & MODE_HBLANK) { //HBLANK Start
|
||||
if (difference >= HBLANK_TIME_ ) {
|
||||
hScanlineOptimization(difference, (SCANLINE_ + HBLANK_TIME_), 1);
|
||||
rcntStartGate(0);
|
||||
psxCheckStartGate(0);
|
||||
counters[4].sCycle = cpuRegs.cycle;
|
||||
counters[4].mode = MODE_HRENDER;
|
||||
}
|
||||
}
|
||||
else { //HBLANK END / HRENDER Begin
|
||||
if (difference >= (HRENDER_TIME_)) {
|
||||
hScanlineOptimization(difference, (SCANLINE_ + HRENDER_TIME_), 1);
|
||||
if (CSRw & 0x4) GSCSRr |= 4; // signal
|
||||
if (!(GSIMR&0x400)) gsIrq();
|
||||
if (gates) rcntEndGate(0);
|
||||
if (psxhblankgate) psxCheckEndGate(0);
|
||||
counters[4].sCycle = cpuRegs.cycle;
|
||||
counters[4].mode = MODE_HBLANK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vSync()
|
||||
{
|
||||
hScanline();
|
||||
|
||||
if ((cpuRegs.cycle - counters[5].sCycle) >= (VSYNC_HALF_)) {
|
||||
if (counters[5].mode == MODE_VSYNC) {
|
||||
VSyncEnd();
|
||||
counters[5].mode = MODE_VRENDER;
|
||||
}
|
||||
else {
|
||||
VSyncStart();
|
||||
counters[5].mode = MODE_VSYNC;
|
||||
}
|
||||
counters[5].sCycle = cpuRegs.cycle;
|
||||
//__Log("%u %u 0\n", cpuRegs.cycle-s_lastvsync[1], timeGetTime()-s_lastvsync[0]);
|
||||
//s_lastvsync[0] = timeGetTime();
|
||||
//s_lastvsync[1] = cpuRegs.cycle;
|
||||
}
|
||||
}
|
||||
|
||||
void rcntUpdate()
|
||||
{
|
||||
int i;
|
||||
u32 change = 0;
|
||||
for (i=0; i<=3; i++) {
|
||||
if ( gates & (1<<i) ) continue;
|
||||
if(gates & (1<<i) ) {
|
||||
//SysPrintf("Stopped accidental update of ee counter %x when using a gate\n", i);
|
||||
continue;
|
||||
}
|
||||
if ((counters[i].mode & 0x80) && (counters[i].mode & 0x3) != 0x3) {
|
||||
//counters[i].count += (cpuRegs.cycle - counters[i].sCycleT) / counters[i].rate;
|
||||
//counters[i].sCycleT = cpuRegs.cycle;
|
||||
|
||||
u32 change = cpuRegs.cycle - counters[i].sCycleT;
|
||||
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 counters[i].sCycleT = cpuRegs.cycle;
|
||||
}
|
||||
else change = 0;
|
||||
|
||||
vSync();
|
||||
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 (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++;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
if((counters[5].mode & 0x10000)) {
|
||||
if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT){
|
||||
//counters[5].sCycleT = cpuRegs.cycle;
|
||||
counters[5].CycleT = VBLANKCNT(counters[5].count);
|
||||
VSync();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 (counters[i].count >= counters[i].target) { // Target interrupt
|
||||
if ((s64)(counters[i].target - counters[i].count) <= 0 /*&& (counters[i].target & 0xffff) > 0*/) { // Target interrupt
|
||||
|
||||
counters[i].target &= 0xffff;
|
||||
//if((counters[i].target > 0xffff)) {
|
||||
//SysPrintf("EE Correcting target %x after reset on target\n", i);
|
||||
counters[i].target &= 0xffff;
|
||||
//}
|
||||
|
||||
if(counters[i].mode & 0x100) {
|
||||
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; // Equal Target flag
|
||||
hwIntcIrq(counters[i].interrupt);
|
||||
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
|
||||
hwIntcIrq(counters[i].interrupt);
|
||||
|
||||
if (counters[i].mode & 0x40) { //The PS2 only resets if the interrupt is enabled - Tested on PS2
|
||||
counters[i].count -= counters[i].target; // Reset on target
|
||||
}
|
||||
else counters[i].target |= 0x10000000;
|
||||
}
|
||||
else counters[i].target |= 0x10000000;
|
||||
if (counters[i].mode & 0x40) { //The PS2 only resets if the interrupt is enabled - Tested on PS2
|
||||
counters[i].count -= counters[i].target; // Reset on target
|
||||
}
|
||||
else counters[i].target += 0x10000000;
|
||||
}
|
||||
else counters[i].target += 0x10000000;
|
||||
|
||||
}
|
||||
|
||||
if (counters[i].count > 0xffff) {
|
||||
|
||||
if (counters[i].mode & 0x0200) { // Overflow interrupt
|
||||
EECNT_LOG("EE counter %d overflow mode %x count %x target %x\n", i, counters[i].mode, counters[i].count, counters[i].target);
|
||||
counters[i].mode |= 0x0800; // Overflow flag
|
||||
counters[i].mode|= 0x0800; // Overflow flag
|
||||
hwIntcIrq(counters[i].interrupt);
|
||||
//SysPrintf("counter[%d] overflow interrupt (%x)\n", i, cpuRegs.cycle);
|
||||
}
|
||||
counters[i].count -= 0x10000;
|
||||
counters[i].target &= 0xffff;
|
||||
}
|
||||
//if(counters[i].target > 0xffff) {
|
||||
//SysPrintf("EE %x Correcting target on overflow\n", i);
|
||||
counters[i].target &= 0xffff;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
rcntSet();
|
||||
}
|
||||
|
||||
void rcntWcount(int index, u32 value)
|
||||
{
|
||||
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;
|
||||
counters[index].target &= 0xffff;
|
||||
//if(counters[index].target > 0xffff) {
|
||||
//SysPrintf("EE Counter %x count write, target > 0xffff\n", index);
|
||||
counters[index].target &= 0xffff;
|
||||
//}
|
||||
//rcntUpd(index);
|
||||
|
||||
if((counters[index].mode & 0x3) != 0x3) {
|
||||
//counters[index].sCycleT = cpuRegs.cycle;
|
||||
|
||||
u32 change = cpuRegs.cycle - counters[index].sCycleT;
|
||||
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) {
|
||||
//counters[index].count += (cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate;
|
||||
//counters[index].sCycleT = cpuRegs.cycle;
|
||||
|
||||
u32 change = cpuRegs.cycle - counters[index].sCycleT;
|
||||
if((counters[index].mode & 0x3) != 0x3){
|
||||
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;
|
||||
|
||||
counters[index].mode &= ~(value & 0xc00); //Clear status flags, the ps2 only clears what is given in the value
|
||||
//if((value & 0x80) && !(counters[index].mode & 0x80)) rcntUpd(index); //Counter wasnt started, so set the start cycle
|
||||
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;
|
||||
case 2: counters[index].rate = 512; break;
|
||||
case 3: counters[index].rate = SCANLINE_; break;
|
||||
case 3: counters[index].rate = PS2HBLANK; break;
|
||||
}
|
||||
|
||||
if((counters[index].mode & 0xF) == 0x7) {
|
||||
gates &= ~(1<<index);
|
||||
SysPrintf("Counters: Gate Disabled\n");
|
||||
SysPrintf("Gate Disabled\n");
|
||||
//counters[index].mode &= ~0x80;
|
||||
}
|
||||
else if (counters[index].mode & 0x4) {
|
||||
gates |= (1<<index);
|
||||
counters[index].mode &= ~0x80;
|
||||
rcntReset(index);
|
||||
// SysPrintf("Gate enable on counter %x mode %x\n", index, counters[index].mode);
|
||||
gates |= 1<<index;
|
||||
counters[index].mode &= ~0x80;
|
||||
rcntReset(index);
|
||||
}
|
||||
else gates &= ~(1<<index);
|
||||
|
||||
/*if ((value & 0x580) == 0x580) { // If we need to compare the target value again, correct the target
|
||||
/*if((counters[index].target > 0xffff) && (counters[index].target & 0xffff) > rcntCycle(index)) {
|
||||
//SysPrintf("EE Correcting target %x after mode write\n", index);
|
||||
counters[index].target &= 0xffff;
|
||||
}*/
|
||||
|
@ -558,69 +618,89 @@ void rcntWmode(int index, u32 value)
|
|||
rcntSet();
|
||||
}
|
||||
|
||||
void rcntStartGate(unsigned int mode) {
|
||||
void rcntStartGate(unsigned int mode){
|
||||
int i;
|
||||
|
||||
for (i=0; i <=3; i++) { //Gates for counters
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((mode == 0) && ((counters[i].mode & 0x83) == 0x83)) counters[i].count += HBLANK_COUNTER_SPEED; //Update counters using the hblank as the clock
|
||||
if (!(gates & (1<<i))) continue;
|
||||
for(i=0; i <=3; i++){ //Gates for counters
|
||||
if(!(gates & (1<<i))) continue;
|
||||
if ((counters[i].mode & 0x8) != mode) continue;
|
||||
|
||||
switch (counters[i].mode & 0x30) {
|
||||
case 0x00: //Count When Signal is low (off)
|
||||
counters[i].mode &= ~0x80; // Stop Counting since signal is On
|
||||
//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)
|
||||
counters[i].count = rcntRcount(i);
|
||||
rcntUpd(i);
|
||||
counters[i].mode &= ~0x80;
|
||||
break;
|
||||
case 0x10: //Reset and start counting on Vsync start
|
||||
case 0x30: //Reset and start counting on Vsync start and end
|
||||
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
|
||||
//Do Nothing
|
||||
break;
|
||||
case 0x3: //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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
switch (counters[i].mode & 0x30) {
|
||||
case 0x00: //Count When Signal is low (off)
|
||||
counters[i].mode |= 0x80; // Start Counting since signal is Off
|
||||
counters[i].count = rcntRcount(i);
|
||||
//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)
|
||||
rcntUpd(i);
|
||||
counters[i].mode |= 0x80;
|
||||
break;
|
||||
case 0x20: //Reset and start counting on Vsync end
|
||||
case 0x30: //Reset and start counting on Vsync start and end
|
||||
case 0x1: //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
|
||||
counters[i].mode |= 0x80;
|
||||
rcntReset(i);
|
||||
counters[i].target &= 0xffff;
|
||||
break;
|
||||
default:
|
||||
SysPrintf("EE Start Counter %x Gate error\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
counters[index].target += 0x10000000;
|
||||
}
|
||||
rcntSet();
|
||||
}
|
||||
|
||||
void rcntWhold(int index, u32 value) {
|
||||
EECNT_LOG("EE hold write %d value %x\n", index, value);
|
||||
if (value & 0xffff0000) SysPrintf("rcntWhold: bad value\n");
|
||||
counters[index].hold = value & 0xffff;
|
||||
counters[index].hold = value;
|
||||
}
|
||||
|
||||
u32 rcntRcount(int index) {
|
||||
|
@ -637,9 +717,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,69 +26,6 @@ typedef struct {
|
|||
u32 CycleT, sCycleT;
|
||||
} Counter;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// SPEED HACKS!!! (1 is normal) (They have inverse affects, only set 1 at a time)
|
||||
//------------------------------------------------------------------
|
||||
#define HBLANK_COUNTER_SPEED 1 //Set to '3' to double the speed of games like KHII
|
||||
#define HBLANK_TIMER_SLOWDOWN 1 //Set to '2' to increase the speed of games like God of War (FPS will be less, but game will be faster)
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// NTSC Timing Information!!! (some scanline info is guessed)
|
||||
//------------------------------------------------------------------
|
||||
#define SCANLINE_NTSC (PS2CLK / 15734.25)//18743
|
||||
#define HRENDER_TIME_NTSC (u32)(SCANLINE_NTSC / 2)//15528 //time from hblank end to hblank start (PS2CLK / 18991.368423051722991900181367568)
|
||||
#define HBLANK_TIME_NTSC (u32)(SCANLINE_NTSC / 2)//3215 //time from hblank start to hblank end (PS2CLK / 91738.91105912572817760653181028)
|
||||
#define VSYNC_NTSC (PS2CLK / 59.94) //hz
|
||||
#define VSYNC_HALF_NTSC (VSYNC_NTSC / 2) //hz
|
||||
|
||||
#define SCANLINES_TOTAL_NTSC 525 // total number of scanlines
|
||||
#define SCANLINES_VSYNC_NTSC 3 // scanlines that are used for syncing every half-frame
|
||||
#define SCANLINES_VRENDER_NTSC 240 // scanlines in a half-frame (because of interlacing)
|
||||
#define SCANLINES_VBLANK1_NTSC 19 // scanlines used for vblank1 (even interlace)
|
||||
#define SCANLINES_VBLANK2_NTSC 20 // scanlines used for vblank2 (odd interlace)
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// PAL Timing Information!!! (some scanline info is guessed)
|
||||
//------------------------------------------------------------------
|
||||
#define SCANLINE_PAL (PS2CLK / 15625)//18874
|
||||
#define HRENDER_TIME_PAL (u32)(SCANLINE_PAL / 2)//15335 //time from hblank end to hblank start
|
||||
#define HBLANK_TIME_PAL (u32)(SCANLINE_PAL / 2)//3539 //time from hblank start to hblank end
|
||||
#define VSYNC_PAL (PS2CLK / 50) //hz
|
||||
#define VSYNC_HALF_PAL (VSYNC_PAL / 2) //hz
|
||||
|
||||
#define SCANLINES_TOTAL_PAL 625 // total number of scanlines
|
||||
#define SCANLINES_VSYNC_PAL 5 // scanlines that are used for syncing every half-frame
|
||||
#define SCANLINES_VRENDER_PAL 288 // scanlines in a half-frame (because of interlacing)
|
||||
#define SCANLINES_VBLANK1_PAL 19 // scanlines used for vblank1 (even interlace)
|
||||
#define SCANLINES_VBLANK2_PAL 20 // scanlines used for vblank2 (odd interlace)
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Timing (PAL/NTSC) Information!!!
|
||||
//------------------------------------------------------------------
|
||||
#define SCANLINE_ (u32)((Config.PsxType&1) ? SCANLINE_PAL : SCANLINE_NTSC) * HBLANK_TIMER_SLOWDOWN
|
||||
#define HRENDER_TIME_ (u32)((Config.PsxType&1) ? HRENDER_TIME_PAL : HRENDER_TIME_NTSC) * HBLANK_TIMER_SLOWDOWN
|
||||
#define HBLANK_TIME_ (u32)((Config.PsxType&1) ? HBLANK_TIME_PAL : HBLANK_TIME_NTSC) * HBLANK_TIMER_SLOWDOWN
|
||||
#define VSYNC_ (u32)((Config.PsxType&1) ? VSYNC_PAL : VSYNC_NTSC)
|
||||
#define VSYNC_HALF_ (u32)((Config.PsxType&1) ? VSYNC_HALF_PAL : VSYNC_HALF_NTSC)
|
||||
|
||||
#define SCANLINES_TOTAL_ (u32)((Config.PsxType&1) ? SCANLINES_TOTAL_PAL : SCANLINES_TOTAL_NTSC)
|
||||
#define SCANLINES_VSYNC_ (u32)((Config.PsxType&1) ? SCANLINES_VSYNC_PAL : SCANLINES_VSYNC_NTSC)
|
||||
#define SCANLINES_VRENDER_ (u32)((Config.PsxType&1) ? SCANLINES_VRENDER_PAL : SCANLINES_VRENDER_NTSC)
|
||||
#define SCANLINES_VBLANK1_ (u32)((Config.PsxType&1) ? SCANLINES_VBLANK1_PAL : SCANLINES_VBLANK1_NTSC)
|
||||
#define SCANLINES_VBLANK2_ (u32)((Config.PsxType&1) ? SCANLINES_VBLANK2_PAL : SCANLINES_VBLANK2_NTSC)
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// vSync and hBlank Timing Modes
|
||||
//------------------------------------------------------------------
|
||||
#define MODE_VRENDER 0x0 //Set during the Render/Frame Scanlines
|
||||
#define MODE_VBLANK 0x1 //Set during the Blanking Scanlines
|
||||
#define MODE_VSYNC 0x3 //Set during the Syncing Scanlines
|
||||
#define MODE_VBLANK1 0x0 //Set during the Blanking Scanlines (half-frame 1)
|
||||
#define MODE_VBLANK2 0x1 //Set during the Blanking Scanlines (half-frame 2)
|
||||
#define MODE_HRENDER 0x0 //Set for ~5/6 of 1 Scanline
|
||||
#define MODE_HBLANK 0x1 //Set for the remaining ~1/6 of 1 Scanline
|
||||
|
||||
|
||||
extern Counter counters[6];
|
||||
extern u32 nextCounter, nextsCounter;
|
||||
|
||||
|
@ -100,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();
|
||||
|
|
Loading…
Reference in New Issue