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