diff options
Diffstat (limited to 'win32/plugins/peopsxgl/winsrc/fps.c')
| -rwxr-xr-x[-rw-r--r--] | win32/plugins/peopsxgl/winsrc/fps.c | 1282 |
1 files changed, 641 insertions, 641 deletions
diff --git a/win32/plugins/peopsxgl/winsrc/fps.c b/win32/plugins/peopsxgl/winsrc/fps.c index 6faf82c6..2e751107 100644..100755 --- a/win32/plugins/peopsxgl/winsrc/fps.c +++ b/win32/plugins/peopsxgl/winsrc/fps.c @@ -1,641 +1,641 @@ -/***************************************************************************
- fps.c - description
- -------------------
- begin : Sun Mar 08 2009
- copyright : (C) 1999-2009 by Pete Bernert
- web : www.pbernert.com
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. See also the license.txt file for *
- * additional informations. *
- * *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2009/03/08 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#include "stdafx.h"
-
-#define _IN_FPS
-
-#include "externals.h"
-
-////////////////////////////////////////////////////////////////////////
-// FPS stuff
-////////////////////////////////////////////////////////////////////////
-
-BOOL bIsPerformanceCounter=FALSE;
-float fFrameRateHz=0;
-DWORD dwFrameRateTicks=16;
-float fFrameRate;
-int iFrameLimit;
-BOOL bUseFrameLimit=FALSE;
-BOOL bUseFrameSkip=0;
-DWORD dwLaceCnt=0;
-
-LARGE_INTEGER liCPUFrequency;
-
-////////////////////////////////////////////////////////////////////////
-// FPS skipping / limit
-////////////////////////////////////////////////////////////////////////
-
-BOOL bInitCap = TRUE;
-float fps_skip = 0;
-float fps_cur = 0;
-
-void FrameCap (void)
-{
- static DWORD curticks, lastticks, _ticks_since_last_update;
- static DWORD TicksToWait = 0;
- static LARGE_INTEGER CurrentTime;
- static LARGE_INTEGER LastTime;
- static BOOL SkipNextWait = FALSE;
- BOOL Waiting = TRUE;
-
- //---------------------------------------------------------
- // init some static vars...
- // bInitCap is TRUE on startup and everytime the user
- // is toggling the frame limit
- //---------------------------------------------------------
-
- if(bInitCap)
- {
- bInitCap=FALSE;
- if (bIsPerformanceCounter)
- QueryPerformanceCounter(&LastTime);
- lastticks = timeGetTime();
- TicksToWait=0;
- return;
- }
-
- //---------------------------------------------------------
-
- if(bIsPerformanceCounter)
- {
- QueryPerformanceCounter(&CurrentTime);
- _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
-
- //---------------------------------------------------------
- // check if diff > 1/2 sec, if yes: take mm timer value
- //---------------------------------------------------------
-
- curticks = timeGetTime();
- if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))
- {
- if(curticks < lastticks)
- _ticks_since_last_update = dwFrameRateTicks+TicksToWait+1;
- else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;
- }
-
- //---------------------------------------------------------
-
- if ((_ticks_since_last_update > TicksToWait) ||
- (CurrentTime.LowPart < LastTime.LowPart))
- {
- LastTime.HighPart = CurrentTime.HighPart;
- LastTime.LowPart = CurrentTime.LowPart;
-
- lastticks=curticks;
-
- if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks)
- TicksToWait=0;
- else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait);
- }
- else
- {
- while (Waiting)
- {
- QueryPerformanceCounter(&CurrentTime);
- _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
-
- //---------------------------------------------------------
- // check if diff > 1/2 sec, if yes: take mm timer value
- //---------------------------------------------------------
- curticks = timeGetTime();
- if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))
- {
- if(curticks < lastticks)
- _ticks_since_last_update = TicksToWait+1;
- else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;
- }
- //---------------------------------------------------------
-
- if ((_ticks_since_last_update > TicksToWait) ||
- (CurrentTime.LowPart < LastTime.LowPart))
- {
- Waiting = FALSE;
-
- lastticks=curticks;
-
- LastTime.HighPart = CurrentTime.HighPart;
- LastTime.LowPart = CurrentTime.LowPart;
- TicksToWait = dwFrameRateTicks;
- }
- }
- }
- }
- else
- {
- curticks = timeGetTime();
- _ticks_since_last_update = curticks - lastticks;
-
- if ((_ticks_since_last_update > TicksToWait) ||
- (curticks < lastticks))
- {
- lastticks = curticks;
-
- if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks)
- TicksToWait=0;
- else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait);
- }
- else
- {
- while (Waiting)
- {
- curticks = timeGetTime();
- _ticks_since_last_update = curticks - lastticks;
- if ((_ticks_since_last_update > TicksToWait) ||
- (curticks < lastticks))
- {
- Waiting = FALSE;
- lastticks = curticks;
- TicksToWait = dwFrameRateTicks;
- }
- }
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-#define MAXSKIP 120
-#define MAXLACE 16
-
-void FrameSkip(void)
-{
- static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip
- static DWORD dwLastLace=0; // helper var for frame limitation
- static DWORD curticks, lastticks, _ticks_since_last_update;
- static LARGE_INTEGER CurrentTime;
- static LARGE_INTEGER LastTime;
-
- if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely
-
- if(iNumSkips) // we are in skipping mode?
- {
- dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces)
- bSkipNextFrame = TRUE; // -> we skip next frame
- iNumSkips--; // -> ok, one done
- }
- else // ok, no additional skipping has to be done...
- { // we check now, if some limitation is needed, or a new skipping has to get started
- DWORD dwWaitTime;
-
- if(bInitCap || bSkipNextFrame) // first time or we skipped before?
- {
- if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called?
- {
- DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame
- dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame
-
- if(bIsPerformanceCounter) // -> now we calc the time of the last drawn frame + the time we spent skipping
- {
- QueryPerformanceCounter(&CurrentTime);
- _ticks_since_last_update= dwT+CurrentTime.LowPart - LastTime.LowPart;
- }
- else
- {
- curticks = timeGetTime();
- _ticks_since_last_update= dwT+curticks - lastticks;
- }
-
- dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed
-
- if(_ticks_since_last_update<dwWaitTime) // -> we were too fast?
- {
- if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent
- (60*dwFrameRateTicks)) // wrong waiting times
- _ticks_since_last_update=dwWaitTime;
-
- while(_ticks_since_last_update<dwWaitTime) // -> loop until we have reached the real psx time
- { // (that's the additional limitation, yup)
- if(bIsPerformanceCounter)
- {
- QueryPerformanceCounter(&CurrentTime);
- _ticks_since_last_update = dwT+CurrentTime.LowPart - LastTime.LowPart;
- }
- else
- {
- curticks = timeGetTime();
- _ticks_since_last_update = dwT+curticks - lastticks;
- }
- }
- }
- else // we were still too slow ?!!?
- {
- if(iAdditionalSkip<MAXSKIP) // -> well, somewhen we really have to stop skipping on very slow systems
- {
- iAdditionalSkip++; // -> inc our watchdog var
- dwLaceCnt=0; // -> reset lace count
- if(bIsPerformanceCounter) // -> ok, start time of the next frame
- QueryPerformanceCounter(&LastTime);
- lastticks = timeGetTime();
- return; // -> done, we will skip next frame to get more speed
- }
- }
- }
-
- bInitCap=FALSE; // -> ok, we have inited the frameskip func
- iAdditionalSkip=0; // -> init additional skip
- bSkipNextFrame=FALSE; // -> we don't skip the next frame
- if(bIsPerformanceCounter) // -> we store the start time of the next frame
- QueryPerformanceCounter(&LastTime);
- lastticks = timeGetTime();
- dwLaceCnt=0; // -> and we start to count the laces
- dwLastLace=0;
- _ticks_since_last_update=0;
- return; // -> done, the next frame will get drawn
- }
-
- bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first
-
- if(bIsPerformanceCounter) // get the current time (we are now at the end of one drawn frame)
- {
- QueryPerformanceCounter(&CurrentTime);
- _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
- }
- else
- {
- curticks = timeGetTime();
- _ticks_since_last_update = curticks - lastticks;
- }
-
- dwLastLace=dwLaceCnt; // store curr count (frame limitation helper)
- dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time'
-
- if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame...
- {
- if(bUseFrameLimit) // if limitation, we skip just next frame,
- { // and decide after, if we need to do more
- iNumSkips=0;
- }
- else
- {
- iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up
- iNumSkips--; // -> since we already skip next frame, one down
- if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line
- }
- bSkipNextFrame = TRUE; // -> signal for skipping the next frame
- }
- else // we were faster than real psx? fine :)
- if(bUseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached
- {
- if(dwLaceCnt>MAXLACE) // -> security check
- _ticks_since_last_update=dwWaitTime;
-
- while(_ticks_since_last_update<dwWaitTime) // just do a waiting loop...
- {
- if(bIsPerformanceCounter)
- {
- QueryPerformanceCounter(&CurrentTime);
- _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
- }
- else
- {
- curticks = timeGetTime();
- _ticks_since_last_update = curticks - lastticks;
- }
- }
- }
-
- if(bIsPerformanceCounter) // ok, start time of the next frame
- QueryPerformanceCounter(&LastTime);
- lastticks = timeGetTime();
- }
-
- dwLaceCnt=0; // init lace counter
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void calcfps(void)
-{
- static DWORD curticks,_ticks_since_last_update,lastticks;
- static long fps_cnt = 0;
- static DWORD fps_tck = 1;
- static LARGE_INTEGER CurrentTime;
- static LARGE_INTEGER LastTime;
- static long fpsskip_cnt = 0;
- static DWORD fpsskip_tck = 1;
-
- if(bIsPerformanceCounter)
- {
- QueryPerformanceCounter(&CurrentTime);
- _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart;
-
- //--------------------------------------------------//
- curticks = timeGetTime();
- if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))
- _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;
- lastticks=curticks;
- //--------------------------------------------------//
-
- if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update)
- fps_skip=min(fps_skip,(((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update) +1.0f));
-
- LastTime.HighPart = CurrentTime.HighPart;
- LastTime.LowPart = CurrentTime.LowPart;
- }
- else
- {
- curticks = timeGetTime();
- _ticks_since_last_update=curticks-lastticks;
-
- if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update)
- fps_skip=min(fps_skip,((float)1000/(float)_ticks_since_last_update+1.0f));
-
- lastticks = curticks;
- }
-
- if(bUseFrameSkip && bUseFrameLimit)
- {
- fpsskip_tck += _ticks_since_last_update;
-
- if(++fpsskip_cnt==2)
- {
- if(bIsPerformanceCounter)
- fps_skip = ((float)liCPUFrequency.LowPart) / ((float)fpsskip_tck) *2.0f;
- else
- fps_skip = (float)2000/(float)fpsskip_tck;
-
- fps_skip +=6.0f;
-
- fpsskip_cnt = 0;
- fpsskip_tck = 1;
- }
- }
-
- fps_tck += _ticks_since_last_update;
-
- if(++fps_cnt==10)
- {
- if(bIsPerformanceCounter)
- fps_cur = ((float)liCPUFrequency.LowPart) / ((float)fps_tck) *10.0f;
- else
- fps_cur = (float)10000/(float)fps_tck;
-
- fps_cnt = 0;
- fps_tck = 1;
-
- if(bUseFrameLimit && fps_cur>fFrameRateHz) // optical adjust ;) avoids flickering fps display
- fps_cur=fFrameRateHz;
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-// PC FPS skipping / limit
-////////////////////////////////////////////////////////////////////////
-
-void PCFrameCap(void)
-{
- static DWORD curticks, lastticks, _ticks_since_last_update;
- static DWORD TicksToWait = 0;
- static LARGE_INTEGER CurrentTime;
- static LARGE_INTEGER LastTime;
- BOOL Waiting = TRUE;
-
- while (Waiting)
- {
- if(bIsPerformanceCounter)
- {
- QueryPerformanceCounter(&CurrentTime);
- _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
-
- //------------------------------------------------//
- curticks = timeGetTime();
- if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))
- {
- if(curticks < lastticks)
- _ticks_since_last_update = TicksToWait+1;
- else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;
- }
- //------------------------------------------------//
-
- if ((_ticks_since_last_update > TicksToWait) ||
- (CurrentTime.LowPart < LastTime.LowPart))
- {
- Waiting = FALSE;
-
- lastticks=curticks;
-
- LastTime.HighPart = CurrentTime.HighPart;
- LastTime.LowPart = CurrentTime.LowPart;
- TicksToWait = (liCPUFrequency.LowPart / fFrameRateHz);
- }
- }
- else
- {
- curticks = timeGetTime();
- _ticks_since_last_update = curticks - lastticks;
- if ((_ticks_since_last_update > TicksToWait) ||
- (curticks < lastticks))
- {
- Waiting = FALSE;
- lastticks = curticks;
- TicksToWait = (1000 / (DWORD)fFrameRateHz);
- }
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void PCcalcfps(void)
-{
- static DWORD curticks,_ticks_since_last_update,lastticks;
- static long fps_cnt = 0;
- static float fps_acc = 0;
- static LARGE_INTEGER CurrentTime;
- static LARGE_INTEGER LastTime;
- float CurrentFPS=0;
-
- if(bIsPerformanceCounter)
- {
- QueryPerformanceCounter(&CurrentTime);
- _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart;
-
- //--------------------------------------------------//
- curticks = timeGetTime();
- if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))
- _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;
- lastticks=curticks;
- //--------------------------------------------------//
-
- if(_ticks_since_last_update)
- {
- CurrentFPS = ((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update);
- }
- else CurrentFPS = 0;
- LastTime.HighPart = CurrentTime.HighPart;
- LastTime.LowPart = CurrentTime.LowPart;
- }
- else
- {
- curticks = timeGetTime();
- if(_ticks_since_last_update=curticks-lastticks)
- CurrentFPS=(float)1000/(float)_ticks_since_last_update;
- else CurrentFPS = 0;
- lastticks = curticks;
- }
-
- fps_acc += CurrentFPS;
-
- if(++fps_cnt==10)
- {
- fps_cur = fps_acc / 10;
- fps_acc = 0;
- fps_cnt = 0;
- }
-
- fps_skip=CurrentFPS+1.0f;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void SetAutoFrameCap(void)
-{
- if(iFrameLimit==1)
- {
- fFrameRateHz = fFrameRate;
- if(bIsPerformanceCounter)
- dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz);
- else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz);
- return;
- }
-
- if(dwActFixes&128)
- {
- if (PSXDisplay.Interlaced)
- fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f;
- else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f;
- }
- else
- {
- //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f;
-
- if(PSXDisplay.PAL)
- {
- if (STATUSREG&GPUSTATUS_INTERLACED)
- fFrameRateHz=33868800.0f/677343.75f; // 50.00238
- else fFrameRateHz=33868800.0f/680595.00f; // 49.76351
- }
- else
- {
- if (STATUSREG&GPUSTATUS_INTERLACED)
- fFrameRateHz=33868800.0f/565031.25f; // 59.94146
- else fFrameRateHz=33868800.0f/566107.50f; // 59.82750
- }
-
- if(bIsPerformanceCounter)
- dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz);
- else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz);
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void InitFrameCap(void) // inits cpu frequency info (on gpu startup)
-{
- if (QueryPerformanceFrequency (&liCPUFrequency))
- bIsPerformanceCounter = TRUE;
- else bIsPerformanceCounter = FALSE;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void ReInitFrameCap(void)
-{
- BOOL bOldPerformanceCounter=bIsPerformanceCounter; // store curr timer mode
-
- if(dwActFixes&0x10000) // check game fix... high performance counters are bad on some mb chipsets
- bIsPerformanceCounter=FALSE;
- else
- {
- if (QueryPerformanceFrequency (&liCPUFrequency))
- bIsPerformanceCounter = TRUE;
- else bIsPerformanceCounter = FALSE;
- }
-
- if(bOldPerformanceCounter!=bIsPerformanceCounter) // changed?
- {
- bInitCap = TRUE;
- SetAutoFrameCap();
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void SetFrameRateConfig(void)
-{
- if(fFrameRateHz==0)
- {
- if(iFrameLimit==2) fFrameRateHz=59.94f; // auto framerate? set some init val (no pal/ntsc known yet)
- else fFrameRateHz=fFrameRate; // else set user framerate
- }
-
- if(bIsPerformanceCounter)
- dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz);
- else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz);
-}
-
-void CheckFrameRate(void) // called in updatelace (on every emulated psx vsync)
-{
- if(bUseFrameSkip)
- {
- if(!(dwActFixes&0x100))
- {
- dwLaceCnt++; // -> and store cnt of vsync between frames
- if(dwLaceCnt>=MAXLACE && bUseFrameLimit)
- {
- if(dwLaceCnt==MAXLACE) bInitCap=TRUE;
- FrameCap();
- }
- }
- else if(bUseFrameLimit) FrameCap();
- calcfps(); // -> calc fps display in skipping mode
- }
- else // -> non-skipping mode:
- {
- if(bUseFrameLimit) FrameCap();
- if(ulKeybits&KEY_SHOWFPS) calcfps();
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void CALLBACK GPUsetframelimit(unsigned long option) // new EPSXE interface func: main emu can enable/disable fps limitation this way
-{
- bInitCap = TRUE;
-
- if(option==1) // emu says: limit
- {
- bUseFrameLimit=TRUE;bUseFrameSkip=FALSE;iFrameLimit=2;
- SetAutoFrameCap();
- }
- else // emu says: no limit
- {
- bUseFrameLimit=FALSE;
- }
-}
-
-////////////////////////////////////////////////////////////////////////
+/*************************************************************************** + fps.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_FPS + +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// +// FPS stuff +//////////////////////////////////////////////////////////////////////// + +BOOL bIsPerformanceCounter=FALSE; +float fFrameRateHz=0; +DWORD dwFrameRateTicks=16; +float fFrameRate; +int iFrameLimit; +BOOL bUseFrameLimit=FALSE; +BOOL bUseFrameSkip=0; +DWORD dwLaceCnt=0; + +LARGE_INTEGER liCPUFrequency; + +//////////////////////////////////////////////////////////////////////// +// FPS skipping / limit +//////////////////////////////////////////////////////////////////////// + +BOOL bInitCap = TRUE; +float fps_skip = 0; +float fps_cur = 0; + +void FrameCap (void) +{ + static DWORD curticks, lastticks, _ticks_since_last_update; + static DWORD TicksToWait = 0; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + static BOOL SkipNextWait = FALSE; + BOOL Waiting = TRUE; + + //--------------------------------------------------------- + // init some static vars... + // bInitCap is TRUE on startup and everytime the user + // is toggling the frame limit + //--------------------------------------------------------- + + if(bInitCap) + { + bInitCap=FALSE; + if (bIsPerformanceCounter) + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + TicksToWait=0; + return; + } + + //--------------------------------------------------------- + + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + + //--------------------------------------------------------- + // check if diff > 1/2 sec, if yes: take mm timer value + //--------------------------------------------------------- + + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + { + if(curticks < lastticks) + _ticks_since_last_update = dwFrameRateTicks+TicksToWait+1; + else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + } + + //--------------------------------------------------------- + + if ((_ticks_since_last_update > TicksToWait) || + (CurrentTime.LowPart < LastTime.LowPart)) + { + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + + lastticks=curticks; + + if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks) + TicksToWait=0; + else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); + } + else + { + while (Waiting) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + + //--------------------------------------------------------- + // check if diff > 1/2 sec, if yes: take mm timer value + //--------------------------------------------------------- + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + { + if(curticks < lastticks) + _ticks_since_last_update = TicksToWait+1; + else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + } + //--------------------------------------------------------- + + if ((_ticks_since_last_update > TicksToWait) || + (CurrentTime.LowPart < LastTime.LowPart)) + { + Waiting = FALSE; + + lastticks=curticks; + + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + TicksToWait = dwFrameRateTicks; + } + } + } + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + lastticks = curticks; + + if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks) + TicksToWait=0; + else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); + } + else + { + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = dwFrameRateTicks; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#define MAXSKIP 120 +#define MAXLACE 16 + +void FrameSkip(void) +{ + static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip + static DWORD dwLastLace=0; // helper var for frame limitation + static DWORD curticks, lastticks, _ticks_since_last_update; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + + if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely + + if(iNumSkips) // we are in skipping mode? + { + dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) + bSkipNextFrame = TRUE; // -> we skip next frame + iNumSkips--; // -> ok, one done + } + else // ok, no additional skipping has to be done... + { // we check now, if some limitation is needed, or a new skipping has to get started + DWORD dwWaitTime; + + if(bInitCap || bSkipNextFrame) // first time or we skipped before? + { + if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called? + { + DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame + dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame + + if(bIsPerformanceCounter) // -> now we calc the time of the last drawn frame + the time we spent skipping + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update= dwT+CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update= dwT+curticks - lastticks; + } + + dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed + + if(_ticks_since_last_update<dwWaitTime) // -> we were too fast? + { + if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent + (60*dwFrameRateTicks)) // wrong waiting times + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update<dwWaitTime) // -> loop until we have reached the real psx time + { // (that's the additional limitation, yup) + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = dwT+CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = dwT+curticks - lastticks; + } + } + } + else // we were still too slow ?!!? + { + if(iAdditionalSkip<MAXSKIP) // -> well, somewhen we really have to stop skipping on very slow systems + { + iAdditionalSkip++; // -> inc our watchdog var + dwLaceCnt=0; // -> reset lace count + if(bIsPerformanceCounter) // -> ok, start time of the next frame + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + return; // -> done, we will skip next frame to get more speed + } + } + } + + bInitCap=FALSE; // -> ok, we have inited the frameskip func + iAdditionalSkip=0; // -> init additional skip + bSkipNextFrame=FALSE; // -> we don't skip the next frame + if(bIsPerformanceCounter) // -> we store the start time of the next frame + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + dwLaceCnt=0; // -> and we start to count the laces + dwLastLace=0; + _ticks_since_last_update=0; + return; // -> done, the next frame will get drawn + } + + bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first + + if(bIsPerformanceCounter) // get the current time (we are now at the end of one drawn frame) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + } + + dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) + dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' + + if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... + { + if(bUseFrameLimit) // if limitation, we skip just next frame, + { // and decide after, if we need to do more + iNumSkips=0; + } + else + { + iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up + iNumSkips--; // -> since we already skip next frame, one down + if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line + } + bSkipNextFrame = TRUE; // -> signal for skipping the next frame + } + else // we were faster than real psx? fine :) + if(bUseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached + { + if(dwLaceCnt>MAXLACE) // -> security check + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update<dwWaitTime) // just do a waiting loop... + { + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + } + } + } + + if(bIsPerformanceCounter) // ok, start time of the next frame + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + } + + dwLaceCnt=0; // init lace counter +} + +//////////////////////////////////////////////////////////////////////// + +void calcfps(void) +{ + static DWORD curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static DWORD fps_tck = 1; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + static long fpsskip_cnt = 0; + static DWORD fpsskip_tck = 1; + + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart; + + //--------------------------------------------------// + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + lastticks=curticks; + //--------------------------------------------------// + + if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update) + fps_skip=min(fps_skip,(((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update) +1.0f)); + + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + + if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update) + fps_skip=min(fps_skip,((float)1000/(float)_ticks_since_last_update+1.0f)); + + lastticks = curticks; + } + + if(bUseFrameSkip && bUseFrameLimit) + { + fpsskip_tck += _ticks_since_last_update; + + if(++fpsskip_cnt==2) + { + if(bIsPerformanceCounter) + fps_skip = ((float)liCPUFrequency.LowPart) / ((float)fpsskip_tck) *2.0f; + else + fps_skip = (float)2000/(float)fpsskip_tck; + + fps_skip +=6.0f; + + fpsskip_cnt = 0; + fpsskip_tck = 1; + } + } + + fps_tck += _ticks_since_last_update; + + if(++fps_cnt==10) + { + if(bIsPerformanceCounter) + fps_cur = ((float)liCPUFrequency.LowPart) / ((float)fps_tck) *10.0f; + else + fps_cur = (float)10000/(float)fps_tck; + + fps_cnt = 0; + fps_tck = 1; + + if(bUseFrameLimit && fps_cur>fFrameRateHz) // optical adjust ;) avoids flickering fps display + fps_cur=fFrameRateHz; + } +} + +//////////////////////////////////////////////////////////////////////// +// PC FPS skipping / limit +//////////////////////////////////////////////////////////////////////// + +void PCFrameCap(void) +{ + static DWORD curticks, lastticks, _ticks_since_last_update; + static DWORD TicksToWait = 0; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + BOOL Waiting = TRUE; + + while (Waiting) + { + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + + //------------------------------------------------// + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + { + if(curticks < lastticks) + _ticks_since_last_update = TicksToWait+1; + else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + } + //------------------------------------------------// + + if ((_ticks_since_last_update > TicksToWait) || + (CurrentTime.LowPart < LastTime.LowPart)) + { + Waiting = FALSE; + + lastticks=curticks; + + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + TicksToWait = (liCPUFrequency.LowPart / fFrameRateHz); + } + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = (1000 / (DWORD)fFrameRateHz); + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void PCcalcfps(void) +{ + static DWORD curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static float fps_acc = 0; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + float CurrentFPS=0; + + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart; + + //--------------------------------------------------// + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + lastticks=curticks; + //--------------------------------------------------// + + if(_ticks_since_last_update) + { + CurrentFPS = ((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update); + } + else CurrentFPS = 0; + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + } + else + { + curticks = timeGetTime(); + if(_ticks_since_last_update=curticks-lastticks) + CurrentFPS=(float)1000/(float)_ticks_since_last_update; + else CurrentFPS = 0; + lastticks = curticks; + } + + fps_acc += CurrentFPS; + + if(++fps_cnt==10) + { + fps_cur = fps_acc / 10; + fps_acc = 0; + fps_cnt = 0; + } + + fps_skip=CurrentFPS+1.0f; +} + +//////////////////////////////////////////////////////////////////////// + +void SetAutoFrameCap(void) +{ + if(iFrameLimit==1) + { + fFrameRateHz = fFrameRate; + if(bIsPerformanceCounter) + dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz); + else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz); + return; + } + + if(dwActFixes&128) + { + if (PSXDisplay.Interlaced) + fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; + else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; + } + else + { + //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; + + if(PSXDisplay.PAL) + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/677343.75f; // 50.00238 + else fFrameRateHz=33868800.0f/680595.00f; // 49.76351 + } + else + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/565031.25f; // 59.94146 + else fFrameRateHz=33868800.0f/566107.50f; // 59.82750 + } + + if(bIsPerformanceCounter) + dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz); + else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz); + } +} + +//////////////////////////////////////////////////////////////////////// + +void InitFrameCap(void) // inits cpu frequency info (on gpu startup) +{ + if (QueryPerformanceFrequency (&liCPUFrequency)) + bIsPerformanceCounter = TRUE; + else bIsPerformanceCounter = FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +void ReInitFrameCap(void) +{ + BOOL bOldPerformanceCounter=bIsPerformanceCounter; // store curr timer mode + + if(dwActFixes&0x10000) // check game fix... high performance counters are bad on some mb chipsets + bIsPerformanceCounter=FALSE; + else + { + if (QueryPerformanceFrequency (&liCPUFrequency)) + bIsPerformanceCounter = TRUE; + else bIsPerformanceCounter = FALSE; + } + + if(bOldPerformanceCounter!=bIsPerformanceCounter) // changed? + { + bInitCap = TRUE; + SetAutoFrameCap(); + } +} + +//////////////////////////////////////////////////////////////////////// + +void SetFrameRateConfig(void) +{ + if(fFrameRateHz==0) + { + if(iFrameLimit==2) fFrameRateHz=59.94f; // auto framerate? set some init val (no pal/ntsc known yet) + else fFrameRateHz=fFrameRate; // else set user framerate + } + + if(bIsPerformanceCounter) + dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz); + else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz); +} + +void CheckFrameRate(void) // called in updatelace (on every emulated psx vsync) +{ + if(bUseFrameSkip) + { + if(!(dwActFixes&0x100)) + { + dwLaceCnt++; // -> and store cnt of vsync between frames + if(dwLaceCnt>=MAXLACE && bUseFrameLimit) + { + if(dwLaceCnt==MAXLACE) bInitCap=TRUE; + FrameCap(); + } + } + else if(bUseFrameLimit) FrameCap(); + calcfps(); // -> calc fps display in skipping mode + } + else // -> non-skipping mode: + { + if(bUseFrameLimit) FrameCap(); + if(ulKeybits&KEY_SHOWFPS) calcfps(); + } +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetframelimit(unsigned long option) // new EPSXE interface func: main emu can enable/disable fps limitation this way +{ + bInitCap = TRUE; + + if(option==1) // emu says: limit + { + bUseFrameLimit=TRUE;bUseFrameSkip=FALSE;iFrameLimit=2; + SetAutoFrameCap(); + } + else // emu says: no limit + { + bUseFrameLimit=FALSE; + } +} + +//////////////////////////////////////////////////////////////////////// |
