mirror of https://github.com/PCSX2/pcsx2.git
major counters changes; i rewrote the vSync/vBlank/hBlank algorithms. they still need some more tweaks though; and i need to check if the other counters are doing their jobs correctly.
also fixed the counters bug introduced in r220. git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@228 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
parent
ee9dcd4130
commit
55ba76be5d
|
@ -145,7 +145,7 @@ extern TESTRUNARGS g_TestRun;
|
|||
//#define PS2CLK 36864000 /* 294.912 mhz */
|
||||
//#define PSXCLK 9216000 /* 36.864 Mhz */
|
||||
//#define PSXCLK 186864000 /* 36.864 Mhz */
|
||||
#define PS2CLK 294912000 /* 294.912 mhz */
|
||||
#define PS2CLK 294912000 //hz /* 294.912 mhz */
|
||||
|
||||
|
||||
/* Config.PsxType == 1: PAL:
|
||||
|
|
185
pcsx2/Counters.c
185
pcsx2/Counters.c
|
@ -67,13 +67,14 @@ void rcntSet() {
|
|||
}
|
||||
|
||||
//Calculate HBlank
|
||||
c = counters[4].CycleT - (cpuRegs.cycle - counters[4].sCycleT);//HBLANKCNT(0.5);
|
||||
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);//(VBLANKCNT(1) / 2);
|
||||
if (c < nextCounter) nextCounter = c;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void rcntInit() {
|
||||
|
@ -145,16 +146,16 @@ void UpdateVSyncRate() {
|
|||
//else counters[5].rate = (Config.PsxType & 1) ? PS2VBLANK_PAL : PS2VBLANK_NTSC;
|
||||
|
||||
counters[4].mode &= ~0x10000;
|
||||
counters[5].mode &= ~0x10000;
|
||||
counters[5].mode &= ~0x30000;
|
||||
|
||||
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].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;
|
||||
//counters[5].sCycleT = cpuRegs.cycle;
|
||||
|
||||
if (Config.CustomFps > 0) {
|
||||
iTicks = GetTickFrequency() / Config.CustomFps;
|
||||
|
@ -349,22 +350,18 @@ __forceinline void frameLimit()
|
|||
}
|
||||
}
|
||||
|
||||
void VSyncStart() // VSync Start (240 hsyncs)
|
||||
__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
|
||||
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)
|
||||
__forceinline void VSyncEnd() // VSync End (22 hsyncs)
|
||||
{
|
||||
iFrame++;
|
||||
*(u32*)(PS2MEM_GS+0x1000) ^= 0x2000; // swap the vsync field
|
||||
|
@ -378,16 +375,100 @@ void VSyncEnd() // VSync End (22 hsyncs)
|
|||
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
|
||||
hwIntcIrq(3); // HW Irq
|
||||
frameLimit(); // limit FPS (also handles frameskip and VUskip)
|
||||
|
||||
counters[5].mode ^= 0x10000; // Alternate vSync Start/End
|
||||
}
|
||||
|
||||
__forceinline void VBlankStart()
|
||||
{
|
||||
psxVBlankStart(); // psxCounters vSync 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
|
||||
}
|
||||
|
||||
int hScanline()
|
||||
{
|
||||
u32 difference = (cpuRegs.cycle - counters[4].sCycleT);
|
||||
|
||||
if (counters[4].mode & MODE_HBLANK) { //HBLANK Start
|
||||
if (difference >= HBLANK_TIME_ ) {
|
||||
if (difference >= SCANLINE_)
|
||||
counters[4].count += (cpuRegs.cycle - counters[4].sCycleT) / SCANLINE_;
|
||||
rcntStartGate(0);
|
||||
psxCheckStartGate(0);
|
||||
counters[4].sCycleT = cpuRegs.cycle;
|
||||
counters[4].mode ^= MODE_HBLANK;
|
||||
}
|
||||
}
|
||||
else { //HBLANK END / HRENDER Begin
|
||||
if (difference >= (HRENDER_TIME_)) {
|
||||
if (difference >= SCANLINE_)
|
||||
counters[4].count += difference / SCANLINE_;
|
||||
if (CSRw & 0x4) GSCSRr |= 4; // signal
|
||||
if (!(GSIMR&0x400)) gsIrq();
|
||||
if (gates) rcntEndGate(0);
|
||||
if (psxhblankgate) psxCheckEndGate(0);
|
||||
counters[4].count++; //increment counter!
|
||||
counters[4].sCycleT = cpuRegs.cycle;
|
||||
counters[4].mode ^= MODE_HBLANK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void vSync()
|
||||
{
|
||||
if (hScanline()) return; // render the next scanline; if no-change, then exit function
|
||||
|
||||
switch (counters[5].mode & 0x30000) {
|
||||
case MODE_VRENDER: //vRender is running
|
||||
if (counters[4].count > SCANLINES_VRENDER_) { // Check if should change state to VBlank
|
||||
//VRENDER END/VBlank START CODE HERE
|
||||
VBlankStart();
|
||||
counters[4].count -= SCANLINES_VRENDER_;
|
||||
counters[5].mode |= MODE_VBLANK; // Set to VBLANK MODE
|
||||
}
|
||||
break;
|
||||
case MODE_VBLANK: //vBlank is running
|
||||
if (counters[5].mode & MODE_VBLANK2) { //Check if should change state to VSYNC
|
||||
if (counters[4].count > SCANLINES_VBLANK2_) {
|
||||
//VBLANK END/VSYNC START CODE HERE
|
||||
VSyncStart();
|
||||
VBlankEnd();
|
||||
counters[4].count -= SCANLINES_VBLANK2_;
|
||||
counters[5].mode &= ~MODE_VBLANK; // Set to VSYNC MODE
|
||||
counters[5].mode ^= MODE_VBLANK2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (counters[4].count > SCANLINES_VBLANK1_) { //Check if should change state to VSYNC
|
||||
//VBLANK END/VSYNC START CODE HERE
|
||||
VSyncStart();
|
||||
VBlankEnd();
|
||||
counters[4].count -= SCANLINES_VBLANK1_;
|
||||
counters[5].mode &= ~MODE_VBLANK; // Set to VSYNC MODE
|
||||
counters[5].mode ^= MODE_VBLANK2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MODE_VSYNC: //vSync is running
|
||||
if (counters[4].count > SCANLINES_VSYNC_) { //Check if should change state to VRENDER
|
||||
//VSYNC END/RENDER START CODE HERE
|
||||
VSyncEnd();
|
||||
counters[4].count -= SCANLINES_VSYNC_;
|
||||
counters[5].mode |= MODE_VRENDER; // Set to VRENDER MODE
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rcntUpdate()
|
||||
{
|
||||
|
@ -405,48 +486,30 @@ void rcntUpdate()
|
|||
}
|
||||
else counters[i].sCycleT = cpuRegs.cycle;
|
||||
}
|
||||
|
||||
if ((cpuRegs.cycle - counters[4].sCycleT) >= (u32)counters[4].CycleT) {
|
||||
|
||||
/*
|
||||
if ((cpuRegs.cycle - counters[4].sCycleT) >= HBLANKCNT(0.5)) { //hBlank
|
||||
if (counters[4].mode & 0x10000) {
|
||||
if (CSRw & 0x4) GSCSRr |= 4; // signal
|
||||
if (!(GSIMR&0x400)) gsIrq();
|
||||
if (gates) rcntEndGate(0);
|
||||
if (psxhblankgate) psxCheckEndGate(0);
|
||||
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].count++;
|
||||
counters[4].CycleT = HBLANKCNT(counters[4].count) - (HBLANKCNT(0.5));
|
||||
|
||||
rcntStartGate(0);
|
||||
psxCheckStartGate(0);
|
||||
}
|
||||
counters[4].mode ^= 0x10000; // Alternate HBLANK Start/End
|
||||
counters[4].sCycleT = cpuRegs.cycle;
|
||||
}
|
||||
|
||||
if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT) {
|
||||
|
||||
if (counters[5].mode & 0x10000) {
|
||||
counters[5].CycleT = VBLANKCNT(counters[5].count);
|
||||
VSyncEnd();
|
||||
}
|
||||
else {
|
||||
if(counters[5].count >= counters[5].Cycle) { // If count >= 720
|
||||
counters[5].sCycleT += VBLANKCNT(counters[5].Cycle);
|
||||
counters[5].count -= counters[5].Cycle; // Count -= 720
|
||||
}
|
||||
counters[5].count++; // Count += 1
|
||||
counters[5].CycleT = VBLANKCNT(counters[5].count) - (VBLANKCNT(1) / 2);
|
||||
VSyncStart();
|
||||
}
|
||||
|
||||
if ((cpuRegs.cycle - counters[5].sCycleT) >= (VBLANKCNT(1) / 2)) { //vBlank
|
||||
if (counters[5].mode & 0x10000) VSyncEnd();
|
||||
else VSyncStart();
|
||||
counters[5].sCycleT = cpuRegs.cycle;
|
||||
}
|
||||
|
||||
*/
|
||||
vSync();
|
||||
|
||||
for (i=0; i<=3; i++) {
|
||||
if (!(counters[i].mode & 0x80)) continue; // Stopped
|
||||
|
||||
|
@ -539,10 +602,10 @@ void rcntWmode(int index, u32 value)
|
|||
}
|
||||
else gates &= ~(1<<index);
|
||||
|
||||
if ((value & 0x580) == 0x580) { // If we need to compare the target value again, correct the target
|
||||
/*if ((value & 0x580) == 0x580) { // If we need to compare the target value again, correct the target
|
||||
//SysPrintf("EE Correcting target %x after mode write\n", index);
|
||||
counters[index].target &= 0xffff;
|
||||
}
|
||||
}*/
|
||||
|
||||
rcntSet();
|
||||
}
|
||||
|
@ -576,6 +639,7 @@ void rcntStartGate(unsigned int mode) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rcntEndGate(unsigned int mode) {
|
||||
int i;
|
||||
|
||||
|
@ -600,6 +664,7 @@ void rcntEndGate(unsigned int mode) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rcntWtarget(int index, u32 value) {
|
||||
|
||||
EECNT_LOG("EE target write %d target %x value %x\n", index, counters[index].target, value);
|
||||
|
|
|
@ -26,6 +26,61 @@ typedef struct {
|
|||
u32 CycleT, sCycleT;
|
||||
} Counter;
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// NTSC Timing Information!!! (some scanline info is guessed)
|
||||
//------------------------------------------------------------------
|
||||
#define SCANLINE_NTSC 18743 //(PS2CLK / 15734.25)
|
||||
#define HRENDER_TIME_NTSC 15528 //time from hblank end to hblank start (PS2CLK / 18991.368423051722991900181367568)
|
||||
#define HBLANK_TIME_NTSC 3215 //time from hblank start to hblank end (PS2CLK / 91738.91105912572817760653181028)
|
||||
#define VSYNC_NTSC (PS2CLK / 59.94) //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 18874
|
||||
#define HRENDER_TIME_PAL 15335 //time from hblank end to hblank start
|
||||
#define HBLANK_TIME_PAL 3539 //time from hblank start to hblank end
|
||||
#define VSYNC_PAL (PS2CLK / 50) //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)
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// PAL Timing Information!!!
|
||||
//------------------------------------------------------------------
|
||||
#define SCANLINE_ (u32)((Config.PsxType&1) ? SCANLINE_PAL : SCANLINE_NTSC)
|
||||
#define HRENDER_TIME_ (u32)((Config.PsxType&1) ? HRENDER_TIME_PAL : HRENDER_TIME_NTSC)
|
||||
#define HBLANK_TIME_ (u32)((Config.PsxType&1) ? HBLANK_TIME_PAL : HBLANK_TIME_NTSC)
|
||||
#define VSYNC_ (u32)((Config.PsxType&1) ? VSYNC_PAL : VSYNC_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 0x10000 //Set during the Render/Frame Scanlines
|
||||
#define MODE_VSYNC 0x00000 //Set during the Syncing Scanlines
|
||||
#define MODE_VBLANK 0x30000 //Set during the Blanking Scanlines
|
||||
#define MODE_VBLANK2 0x40000 //Set during the Blanking Scanlines (half-frame 2)
|
||||
//#define MODE_DO_ONCE 0x80000 //Do the code once per change of state
|
||||
#define MODE_HRENDER 0x00000 //Set for ~5/6 of 1 Scanline
|
||||
#define MODE_HBLANK 0x10000 //Set for the remaining ~1/6 of 1 Scanline
|
||||
|
||||
|
||||
extern Counter counters[6];
|
||||
extern u32 nextCounter, nextsCounter;
|
||||
|
||||
|
|
|
@ -148,18 +148,19 @@ void psxRcntInit() {
|
|||
psxRcntSet();
|
||||
}
|
||||
|
||||
void psxVSyncStart() {
|
||||
void psxVBlankStart() {
|
||||
cdvdVsync();
|
||||
psxHu32(0x1070)|= 1;
|
||||
if(psxvblankgate & 1) psxCheckStartGate(1);
|
||||
if(psxvblankgate & (1 << 3)) psxCheckStartGate(3);
|
||||
}
|
||||
|
||||
void psxVSyncEnd() {
|
||||
void psxVBlankEnd() {
|
||||
psxHu32(0x1070)|= 0x800;
|
||||
if(psxvblankgate & 1) psxCheckEndGate(1);
|
||||
if(psxvblankgate & (1 << 3)) psxCheckEndGate(3);
|
||||
}
|
||||
|
||||
void psxCheckEndGate(int counter) { //Check Gate events when Vsync Ends
|
||||
int i = counter;
|
||||
//SysPrintf("End Gate %x\n", counter);
|
||||
|
|
|
@ -48,8 +48,8 @@ u32 psxRcntRcount32(int index);
|
|||
u64 psxRcntCycles(int index);
|
||||
int psxRcntFreeze(gzFile f, int Mode);
|
||||
|
||||
void psxVSyncStart();
|
||||
void psxVSyncEnd();
|
||||
void psxVBlankStart();
|
||||
void psxVBlankEnd();
|
||||
void psxCheckStartGate(int counter);
|
||||
void psxCheckEndGate(int counter);
|
||||
|
||||
|
|
Loading…
Reference in New Issue