frontend: tune scanline implementation a bit
[pcsx_rearmed.git] / plugins / gpu-gles / gpuFps.c
1 /***************************************************************************\r
2                           fps.c  -  description\r
3                              -------------------\r
4     begin                : Sun Mar 08 2009\r
5     copyright            : (C) 1999-2009 by Pete Bernert\r
6     web                  : www.pbernert.com   \r
7  ***************************************************************************/\r
8 \r
9 /***************************************************************************\r
10  *                                                                         *\r
11  *   This program is free software; you can redistribute it and/or modify  *\r
12  *   it under the terms of the GNU General Public License as published by  *\r
13  *   the Free Software Foundation; either version 2 of the License, or     *\r
14  *   (at your option) any later version. See also the license.txt file for *\r
15  *   additional informations.                                              *\r
16  *                                                                         *\r
17  ***************************************************************************/\r
18 \r
19 //*************************************************************************// \r
20 // History of changes:\r
21 //\r
22 // 2009/03/08 - Pete  \r
23 // - generic cleanup for the Peops release\r
24 //\r
25 //*************************************************************************// \r
26 \r
27 #ifdef _WINDOWS\r
28 #include "Stdafx.h"\r
29 #include "Externals.h"\r
30 #include "plugin.h"\r
31 #include "Fps.h"\r
32 #include "Prim.h"\r
33 #else\r
34 #include "gpuStdafx.h"\r
35 #include "gpuExternals.h"\r
36 //#include "plugins.h"\r
37 #include "gpuFps.h"\r
38 #include "gpuPrim.h"\r
39 #endif\r
40 \r
41 #define _IN_FPS\r
42 \r
43 #define CALLBACK\r
44 \r
45 ////////////////////////////////////////////////////////////////////////\r
46 // FPS stuff\r
47 ////////////////////////////////////////////////////////////////////////\r
48 #ifdef _WINDOWS\r
49 LARGE_INTEGER  liCPUFrequency;\r
50 #endif\r
51 \r
52 ////////////////////////////////////////////////////////////////////////\r
53 // FPS skipping / limit\r
54 ////////////////////////////////////////////////////////////////////////\r
55 \r
56 BOOL           bIsPerformanceCounter;\r
57 float          fFrameRateHz;\r
58 DWORD          dwFrameRateTicks;\r
59 float          fFrameRate;\r
60 int            iFrameLimit;\r
61 BOOL           bUseFrameLimit;\r
62 BOOL           bUseFrameSkip;\r
63 DWORD          dwLaceCnt;\r
64 \r
65 BOOL         bInitCap; \r
66 float        fps_skip;\r
67 float        fps_cur;\r
68 \r
69 #ifdef _WINDOWS\r
70 \r
71 void FrameCap (void)\r
72 {\r
73  static DWORD curticks, lastticks, _ticks_since_last_update;\r
74  static DWORD TicksToWait = 0;\r
75  static LARGE_INTEGER  CurrentTime;\r
76  static LARGE_INTEGER  LastTime;\r
77  static BOOL SkipNextWait = FALSE;\r
78  BOOL Waiting = TRUE;\r
79 \r
80  //---------------------------------------------------------\r
81  // init some static vars... \r
82  // bInitCap is TRUE on startup and everytime the user\r
83  // is toggling the frame limit\r
84  //---------------------------------------------------------\r
85 \r
86  if(bInitCap)\r
87   {\r
88    bInitCap=FALSE;\r
89    if (bIsPerformanceCounter)\r
90     QueryPerformanceCounter(&LastTime);\r
91    lastticks = timeGetTime();\r
92    TicksToWait=0;\r
93    return;\r
94   }\r
95 \r
96  //---------------------------------------------------------\r
97 \r
98  if(bIsPerformanceCounter)\r
99   {\r
100    QueryPerformanceCounter(&CurrentTime);\r
101    _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;\r
102 \r
103    //---------------------------------------------------------\r
104    // check if diff > 1/2 sec, if yes: take mm timer value\r
105    //---------------------------------------------------------\r
106 \r
107    curticks = timeGetTime();\r
108    if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))   \r
109     {\r
110      if(curticks < lastticks)\r
111           _ticks_since_last_update = dwFrameRateTicks+TicksToWait+1;\r
112      else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;\r
113     }\r
114 \r
115    //---------------------------------------------------------\r
116 \r
117    if ((_ticks_since_last_update > TicksToWait) || \r
118        (CurrentTime.LowPart < LastTime.LowPart))\r
119     {\r
120      LastTime.HighPart = CurrentTime.HighPart;\r
121      LastTime.LowPart  = CurrentTime.LowPart;\r
122 \r
123      lastticks=curticks;\r
124 \r
125      if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks)\r
126           TicksToWait=0;\r
127      else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait);\r
128     }\r
129    else\r
130     {\r
131      while (Waiting)\r
132       {\r
133        QueryPerformanceCounter(&CurrentTime);\r
134        _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;\r
135 \r
136        //---------------------------------------------------------\r
137        // check if diff > 1/2 sec, if yes: take mm timer value\r
138        //---------------------------------------------------------\r
139        curticks = timeGetTime();\r
140        if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))   \r
141         {\r
142          if(curticks < lastticks)\r
143               _ticks_since_last_update = TicksToWait+1;\r
144          else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;\r
145         }\r
146        //---------------------------------------------------------\r
147 \r
148        if ((_ticks_since_last_update > TicksToWait) || \r
149            (CurrentTime.LowPart < LastTime.LowPart))\r
150         {\r
151          Waiting = FALSE;\r
152 \r
153          lastticks=curticks;\r
154 \r
155          LastTime.HighPart = CurrentTime.HighPart;\r
156          LastTime.LowPart = CurrentTime.LowPart;\r
157          TicksToWait = dwFrameRateTicks;\r
158         }\r
159       }\r
160     }\r
161   }\r
162  else\r
163   {\r
164    curticks = timeGetTime();\r
165    _ticks_since_last_update = curticks - lastticks;\r
166 \r
167    if ((_ticks_since_last_update > TicksToWait) || \r
168        (curticks < lastticks))\r
169     {\r
170      lastticks = curticks;\r
171 \r
172      if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks)\r
173           TicksToWait=0;\r
174      else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait);\r
175     }\r
176    else\r
177     {\r
178      while (Waiting)\r
179       {\r
180        curticks = timeGetTime();\r
181        _ticks_since_last_update = curticks - lastticks;\r
182        if ((_ticks_since_last_update > TicksToWait) ||\r
183            (curticks < lastticks))\r
184         {\r
185          Waiting = FALSE;\r
186          lastticks = curticks;\r
187          TicksToWait = dwFrameRateTicks;\r
188         }\r
189       }\r
190     }\r
191   }\r
192 }\r
193 \r
194 ////////////////////////////////////////////////////////////////////////\r
195 \r
196 #define MAXSKIP 120\r
197 #define MAXLACE 16\r
198 \r
199 void FrameSkip(void)\r
200 {\r
201  static int   iNumSkips=0,iAdditionalSkip=0;           // number of additional frames to skip\r
202  static DWORD dwLastLace=0;                            // helper var for frame limitation\r
203  static DWORD curticks, lastticks, _ticks_since_last_update;\r
204  static LARGE_INTEGER  CurrentTime;\r
205  static LARGE_INTEGER  LastTime;\r
206 \r
207  if(!dwLaceCnt) return;                                // important: if no updatelace happened, we ignore it completely\r
208 \r
209  if(iNumSkips)                                         // we are in skipping mode?\r
210   {\r
211    dwLastLace+=dwLaceCnt;                              // -> calc frame limit helper (number of laces)\r
212    bSkipNextFrame = TRUE;                              // -> we skip next frame\r
213    iNumSkips--;                                        // -> ok, one done\r
214   }\r
215  else                                                  // ok, no additional skipping has to be done... \r
216   {                                                    // we check now, if some limitation is needed, or a new skipping has to get started\r
217    DWORD dwWaitTime;\r
218 \r
219    if(bInitCap || bSkipNextFrame)                      // first time or we skipped before?\r
220     {\r
221      if(bUseFrameLimit && !bInitCap)                   // frame limit wanted and not first time called?\r
222       {\r
223        DWORD dwT=_ticks_since_last_update;             // -> that's the time of the last drawn frame\r
224        dwLastLace+=dwLaceCnt;                          // -> and that's the number of updatelace since the start of the last drawn frame\r
225 \r
226        if(bIsPerformanceCounter)                       // -> now we calc the time of the last drawn frame + the time we spent skipping\r
227         {\r
228          QueryPerformanceCounter(&CurrentTime);\r
229          _ticks_since_last_update= dwT+CurrentTime.LowPart - LastTime.LowPart;\r
230         }\r
231        else\r
232         {\r
233          curticks = timeGetTime();\r
234          _ticks_since_last_update= dwT+curticks - lastticks;\r
235         }\r
236 \r
237        dwWaitTime=dwLastLace*dwFrameRateTicks;         // -> and now we calc the time the real psx would have needed\r
238 \r
239        if(_ticks_since_last_update<dwWaitTime)         // -> we were too fast?\r
240         {                                    \r
241          if((dwWaitTime-_ticks_since_last_update)>     // -> some more security, to prevent\r
242             (60*dwFrameRateTicks))                     //    wrong waiting times\r
243           _ticks_since_last_update=dwWaitTime;\r
244 \r
245          while(_ticks_since_last_update<dwWaitTime)    // -> loop until we have reached the real psx time\r
246           {                                            //    (that's the additional limitation, yup)\r
247            if(bIsPerformanceCounter)\r
248             {\r
249              QueryPerformanceCounter(&CurrentTime);\r
250              _ticks_since_last_update = dwT+CurrentTime.LowPart - LastTime.LowPart;\r
251             }\r
252            else\r
253             {\r
254              curticks = timeGetTime();\r
255              _ticks_since_last_update = dwT+curticks - lastticks;\r
256             }\r
257           }\r
258         }\r
259        else                                            // we were still too slow ?!!?\r
260         {\r
261          if(iAdditionalSkip<MAXSKIP)                   // -> well, somewhen we really have to stop skipping on very slow systems\r
262           {\r
263            iAdditionalSkip++;                          // -> inc our watchdog var\r
264            dwLaceCnt=0;                                // -> reset lace count\r
265            if(bIsPerformanceCounter)                   // -> ok, start time of the next frame\r
266             QueryPerformanceCounter(&LastTime);\r
267            lastticks = timeGetTime();\r
268            return;                                     // -> done, we will skip next frame to get more speed\r
269           } \r
270         }\r
271       }\r
272 \r
273      bInitCap=FALSE;                                   // -> ok, we have inited the frameskip func\r
274      iAdditionalSkip=0;                                // -> init additional skip\r
275      bSkipNextFrame=FALSE;                              // -> we don't skip the next frame\r
276      if(bIsPerformanceCounter)                         // -> we store the start time of the next frame\r
277       QueryPerformanceCounter(&LastTime);\r
278      lastticks = timeGetTime();\r
279      dwLaceCnt=0;                                      // -> and we start to count the laces \r
280      dwLastLace=0;      \r
281      _ticks_since_last_update=0;\r
282      return;                                           // -> done, the next frame will get drawn\r
283     }\r
284 \r
285    bSkipNextFrame=FALSE;                                // init the frame skip signal to 'no skipping' first\r
286 \r
287    if(bIsPerformanceCounter)                           // get the current time (we are now at the end of one drawn frame)\r
288     {\r
289      QueryPerformanceCounter(&CurrentTime);\r
290      _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;\r
291     }\r
292    else\r
293     {\r
294      curticks = timeGetTime();\r
295      _ticks_since_last_update = curticks - lastticks;\r
296     }\r
297 \r
298    dwLastLace=dwLaceCnt;                               // store curr count (frame limitation helper)\r
299    dwWaitTime=dwLaceCnt*dwFrameRateTicks;              // calc the 'real psx lace time'\r
300 \r
301    if(_ticks_since_last_update>dwWaitTime)             // hey, we needed way too long for that frame...\r
302     {\r
303      if(bUseFrameLimit)                                // if limitation, we skip just next frame,\r
304       {                                                // and decide after, if we need to do more\r
305        iNumSkips=0;\r
306       }\r
307      else\r
308       {\r
309        iNumSkips=_ticks_since_last_update/dwWaitTime;  // -> calc number of frames to skip to catch up\r
310        iNumSkips--;                                    // -> since we already skip next frame, one down\r
311        if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP;        // -> well, somewhere we have to draw a line\r
312       }\r
313      bSkipNextFrame = TRUE;                            // -> signal for skipping the next frame\r
314     }\r
315    else                                                // we were faster than real psx? fine :)\r
316    if(bUseFrameLimit)                                  // frame limit used? so we wait til the 'real psx time' has been reached\r
317     {\r
318      if(dwLaceCnt>MAXLACE)                             // -> security check\r
319       _ticks_since_last_update=dwWaitTime;\r
320 \r
321      while(_ticks_since_last_update<dwWaitTime)        // just do a waiting loop...\r
322       {\r
323        if(bIsPerformanceCounter)\r
324         {\r
325          QueryPerformanceCounter(&CurrentTime);\r
326          _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;\r
327         }\r
328        else\r
329         {\r
330          curticks = timeGetTime();\r
331          _ticks_since_last_update = curticks - lastticks;\r
332         }\r
333       }\r
334     }\r
335 \r
336    if(bIsPerformanceCounter)                           // ok, start time of the next frame\r
337     QueryPerformanceCounter(&LastTime);\r
338    lastticks = timeGetTime();\r
339   }\r
340 \r
341  dwLaceCnt=0;                                          // init lace counter\r
342 }\r
343 \r
344 ////////////////////////////////////////////////////////////////////////\r
345 \r
346 void calcfps(void)\r
347 {\r
348  static DWORD curticks,_ticks_since_last_update,lastticks;\r
349  static long   fps_cnt = 0;\r
350  static DWORD  fps_tck = 1;\r
351  static LARGE_INTEGER  CurrentTime;\r
352  static LARGE_INTEGER  LastTime;\r
353  static long   fpsskip_cnt = 0;\r
354  static DWORD  fpsskip_tck = 1;\r
355 \r
356  if(bIsPerformanceCounter)\r
357   {\r
358    QueryPerformanceCounter(&CurrentTime);\r
359    _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart;\r
360                                                         \r
361    //--------------------------------------------------//\r
362    curticks = timeGetTime();\r
363    if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))\r
364     _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;\r
365    lastticks=curticks;\r
366    //--------------------------------------------------//\r
367 \r
368    if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update)                                    \r
369     fps_skip=min(fps_skip,(((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update) +1.0f));\r
370 \r
371    LastTime.HighPart = CurrentTime.HighPart;\r
372    LastTime.LowPart = CurrentTime.LowPart;\r
373   }\r
374  else\r
375   {\r
376    curticks = timeGetTime();\r
377    _ticks_since_last_update=curticks-lastticks;\r
378 \r
379    if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update)\r
380     fps_skip=min(fps_skip,((float)1000/(float)_ticks_since_last_update+1.0f));\r
381 \r
382    lastticks = curticks;\r
383   }\r
384 \r
385  if(bUseFrameSkip && bUseFrameLimit)\r
386   {\r
387    fpsskip_tck += _ticks_since_last_update;\r
388 \r
389    if(++fpsskip_cnt==2)\r
390     {\r
391      if(bIsPerformanceCounter)\r
392       fps_skip = ((float)liCPUFrequency.LowPart) / ((float)fpsskip_tck) *2.0f;\r
393      else\r
394       fps_skip = (float)2000/(float)fpsskip_tck;\r
395 \r
396      fps_skip +=6.0f;\r
397 \r
398      fpsskip_cnt = 0;\r
399      fpsskip_tck = 1;\r
400     }\r
401   }\r
402 \r
403  fps_tck += _ticks_since_last_update;\r
404 \r
405  if(++fps_cnt==10)\r
406   {\r
407    if(bIsPerformanceCounter)\r
408     fps_cur = ((float)liCPUFrequency.LowPart) / ((float)fps_tck) *10.0f;\r
409    else\r
410     fps_cur = (float)10000/(float)fps_tck;\r
411 \r
412    fps_cnt = 0;\r
413    fps_tck = 1;\r
414 \r
415    if(bUseFrameLimit && fps_cur>fFrameRateHz)            // optical adjust ;) avoids flickering fps display\r
416     fps_cur=fFrameRateHz;\r
417   }\r
418 }\r
419 \r
420 ////////////////////////////////////////////////////////////////////////\r
421 // PC FPS skipping / limit\r
422 ////////////////////////////////////////////////////////////////////////\r
423 \r
424 void PCFrameCap(void)\r
425 {\r
426  static DWORD curticks, lastticks, _ticks_since_last_update;\r
427  static DWORD TicksToWait = 0;\r
428  static LARGE_INTEGER  CurrentTime;\r
429  static LARGE_INTEGER  LastTime;\r
430  BOOL Waiting = TRUE;\r
431 \r
432  while (Waiting)\r
433   {\r
434    if(bIsPerformanceCounter)\r
435     {\r
436      QueryPerformanceCounter(&CurrentTime);\r
437      _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;\r
438 \r
439      //------------------------------------------------//\r
440      curticks = timeGetTime();\r
441      if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))   \r
442       {\r
443        if(curticks < lastticks)\r
444             _ticks_since_last_update = TicksToWait+1;\r
445        else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;\r
446       }\r
447      //------------------------------------------------//\r
448 \r
449      if ((_ticks_since_last_update > TicksToWait) ||\r
450          (CurrentTime.LowPart < LastTime.LowPart))\r
451       {\r
452        Waiting = FALSE;\r
453 \r
454        lastticks=curticks; \r
455 \r
456        LastTime.HighPart = CurrentTime.HighPart;\r
457        LastTime.LowPart = CurrentTime.LowPart;\r
458        TicksToWait = (liCPUFrequency.LowPart / fFrameRateHz);\r
459       }\r
460     }\r
461    else\r
462     {\r
463      curticks = timeGetTime();\r
464      _ticks_since_last_update = curticks - lastticks;\r
465      if ((_ticks_since_last_update > TicksToWait) || \r
466          (curticks < lastticks))\r
467       {\r
468        Waiting = FALSE;\r
469        lastticks = curticks;\r
470        TicksToWait = (1000 / (DWORD)fFrameRateHz);\r
471       }\r
472     }\r
473   }\r
474 }\r
475 \r
476 ////////////////////////////////////////////////////////////////////////\r
477 \r
478 void PCcalcfps(void)\r
479 {\r
480  static DWORD curticks,_ticks_since_last_update,lastticks;\r
481  static long  fps_cnt = 0;\r
482  static float fps_acc = 0;\r
483  static LARGE_INTEGER  CurrentTime;\r
484  static LARGE_INTEGER  LastTime;\r
485  float CurrentFPS=0;    \r
486  \r
487  if(bIsPerformanceCounter)\r
488   {\r
489    QueryPerformanceCounter(&CurrentTime);\r
490    _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart;\r
491 \r
492    //--------------------------------------------------//\r
493    curticks = timeGetTime();\r
494    if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))   \r
495     _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000;\r
496    lastticks=curticks;\r
497    //--------------------------------------------------//\r
498 \r
499    if(_ticks_since_last_update)\r
500     {\r
501      CurrentFPS = ((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update);\r
502     }\r
503    else CurrentFPS = 0;\r
504    LastTime.HighPart = CurrentTime.HighPart;\r
505    LastTime.LowPart = CurrentTime.LowPart;\r
506   }\r
507  else\r
508   {\r
509    curticks = timeGetTime();\r
510    if(_ticks_since_last_update=curticks-lastticks)\r
511         CurrentFPS=(float)1000/(float)_ticks_since_last_update;\r
512    else CurrentFPS = 0;\r
513    lastticks = curticks;\r
514   }\r
515 \r
516  fps_acc += CurrentFPS;\r
517 \r
518  if(++fps_cnt==10)\r
519   {\r
520    fps_cur = fps_acc / 10;\r
521    fps_acc = 0;\r
522    fps_cnt = 0;\r
523   }\r
524  \r
525  fps_skip=CurrentFPS+1.0f;\r
526 }\r
527 \r
528 ////////////////////////////////////////////////////////////////////////\r
529 \r
530 void SetAutoFrameCap(void)\r
531 {\r
532  if(iFrameLimit==1)\r
533   {\r
534    fFrameRateHz = fFrameRate;\r
535    if(bIsPerformanceCounter)\r
536         dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz);\r
537    else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz);\r
538    return;\r
539   }\r
540 \r
541  if(dwActFixes&128)\r
542   {\r
543    if (PSXDisplay.Interlaced)\r
544         fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f;\r
545    else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f;\r
546   }\r
547  else\r
548   {\r
549    //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f;\r
550 \r
551    if(PSXDisplay.PAL)\r
552     {\r
553      if (STATUSREG&GPUSTATUS_INTERLACED)\r
554            fFrameRateHz=33868800.0f/677343.75f;        // 50.00238\r
555       else fFrameRateHz=33868800.0f/680595.00f;        // 49.76351\r
556     }                                                     \r
557    else\r
558     {\r
559      if (STATUSREG&GPUSTATUS_INTERLACED)\r
560            fFrameRateHz=33868800.0f/565031.25f;        // 59.94146\r
561       else fFrameRateHz=33868800.0f/566107.50f;        // 59.82750\r
562     }\r
563 \r
564    if(bIsPerformanceCounter)\r
565         dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz);\r
566    else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz);\r
567   }\r
568 }\r
569 \r
570 ////////////////////////////////////////////////////////////////////////\r
571 \r
572 void InitFrameCap(void)                                // inits cpu frequency info (on gpu startup)\r
573 {\r
574  if (QueryPerformanceFrequency (&liCPUFrequency))\r
575       bIsPerformanceCounter = TRUE;\r
576  else bIsPerformanceCounter = FALSE;\r
577 }\r
578 \r
579 ////////////////////////////////////////////////////////////////////////\r
580 \r
581 void ReInitFrameCap(void)\r
582 {\r
583  BOOL bOldPerformanceCounter=bIsPerformanceCounter;    // store curr timer mode\r
584 \r
585  if(dwActFixes&0x10000)                                // check game fix... high performance counters are bad on some mb chipsets\r
586       bIsPerformanceCounter=FALSE;\r
587  else \r
588   {\r
589    if (QueryPerformanceFrequency (&liCPUFrequency))\r
590         bIsPerformanceCounter = TRUE;\r
591    else bIsPerformanceCounter = FALSE;\r
592   }\r
593            \r
594  if(bOldPerformanceCounter!=bIsPerformanceCounter)     // changed?\r
595   {\r
596    bInitCap = TRUE;\r
597    SetAutoFrameCap();\r
598   }\r
599 }\r
600 \r
601 ////////////////////////////////////////////////////////////////////////\r
602 \r
603 void SetFrameRateConfig(void)\r
604 {\r
605  if(fFrameRateHz==0) \r
606   {\r
607    if(iFrameLimit==2) fFrameRateHz=59.94f;           // auto framerate? set some init val (no pal/ntsc known yet)\r
608    else               fFrameRateHz=fFrameRate;       // else set user framerate\r
609   }\r
610 \r
611  if(bIsPerformanceCounter)\r
612       dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz);\r
613  else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz);\r
614 }\r
615 \r
616 ////////////////////////////////////////////////////////////////////////\r
617 \r
618 // LINUX ---------------------------------------------\r
619 \r
620 #else\r
621 \r
622 #define TIMEBASE 100000\r
623 \r
624 // hehehe... using same func name as with win32 ;) wow, are we genius ;)\r
625 unsigned long timeGetTime()\r
626 {\r
627  struct timeval tv;\r
628  gettimeofday(&tv, 0);                                // well, maybe there are better ways\r
629  return tv.tv_sec * 100000 + tv.tv_usec/10;           // to do that in linux, but at least it works\r
630 }\r
631 \r
632 void FrameCap(void)\r
633 {\r
634  static unsigned long curticks, lastticks, _ticks_since_last_update;\r
635  static unsigned long TicksToWait = 0;\r
636  bool Waiting = TRUE;\r
637 \r
638   {\r
639    curticks = timeGetTime();\r
640    _ticks_since_last_update = curticks - lastticks;\r
641 \r
642     if((_ticks_since_last_update > TicksToWait) ||\r
643        (curticks <lastticks))\r
644     {\r
645      lastticks = curticks;\r
646 \r
647      if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks)\r
648           TicksToWait=0;\r
649      else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait);\r
650     }\r
651    else\r
652     {\r
653      while (Waiting) \r
654       {\r
655        curticks = timeGetTime(); \r
656        _ticks_since_last_update = curticks - lastticks; \r
657        if ((_ticks_since_last_update > TicksToWait) ||\r
658            (curticks < lastticks)) \r
659         { \r
660          Waiting = FALSE;\r
661          lastticks = curticks;\r
662          TicksToWait = dwFrameRateTicks; \r
663         } \r
664       } \r
665     } \r
666   } \r
667\r
668  \r
669 ////////////////////////////////////////////////////////////////////////\r
670 \r
671 #define MAXSKIP 120\r
672 #define MAXLACE 16\r
673 \r
674 void FrameSkip(void)\r
675 {\r
676  static int   iNumSkips=0,iAdditionalSkip=0;           // number of additional frames to skip\r
677  static DWORD dwLastLace=0;                            // helper var for frame limitation\r
678  static DWORD curticks, lastticks, _ticks_since_last_update;\r
679 \r
680  if(!dwLaceCnt) return;                                // important: if no updatelace happened, we ignore it completely\r
681 \r
682  if(iNumSkips)                                         // we are in skipping mode?\r
683   {\r
684    dwLastLace+=dwLaceCnt;                              // -> calc frame limit helper (number of laces)\r
685    bSkipNextFrame = TRUE;                              // -> we skip next frame\r
686    iNumSkips--;                                        // -> ok, one done\r
687   }\r
688  else                                                  // ok, no additional skipping has to be done... \r
689   {                                                    // we check now, if some limitation is needed, or a new skipping has to get started\r
690    DWORD dwWaitTime;\r
691 \r
692    if(bInitCap || bSkipNextFrame)                      // first time or we skipped before?\r
693     {\r
694      if(bUseFrameLimit && !bInitCap)                   // frame limit wanted and not first time called?\r
695       {\r
696        DWORD dwT=_ticks_since_last_update;             // -> that's the time of the last drawn frame\r
697        dwLastLace+=dwLaceCnt;                          // -> and that's the number of updatelace since the start of the last drawn frame\r
698 \r
699        curticks = timeGetTime();\r
700        _ticks_since_last_update= dwT+curticks - lastticks;\r
701 \r
702        dwWaitTime=dwLastLace*dwFrameRateTicks;         // -> and now we calc the time the real psx would have needed\r
703 \r
704        if(_ticks_since_last_update<dwWaitTime)         // -> we were too fast?\r
705         {                                    \r
706          if((dwWaitTime-_ticks_since_last_update)>     // -> some more security, to prevent\r
707             (60*dwFrameRateTicks))                     //    wrong waiting times\r
708           _ticks_since_last_update=dwWaitTime;\r
709 \r
710          while(_ticks_since_last_update<dwWaitTime)    // -> loop until we have reached the real psx time\r
711           {                                            //    (that's the additional limitation, yup)\r
712            curticks = timeGetTime();\r
713            _ticks_since_last_update = dwT+curticks - lastticks;\r
714           }\r
715         }\r
716        else                                            // we were still too slow ?!!?\r
717         {\r
718          if(iAdditionalSkip<MAXSKIP)                   // -> well, somewhen we really have to stop skipping on very slow systems\r
719           {\r
720            iAdditionalSkip++;                          // -> inc our watchdog var\r
721            dwLaceCnt=0;                                // -> reset lace count\r
722            lastticks = timeGetTime();\r
723            return;                                     // -> done, we will skip next frame to get more speed\r
724           }\r
725         }\r
726       }\r
727 \r
728      bInitCap=FALSE;                                   // -> ok, we have inited the frameskip func\r
729      iAdditionalSkip=0;                                // -> init additional skip\r
730      bSkipNextFrame=FALSE;                             // -> we don't skip the next frame\r
731      lastticks = timeGetTime();\r
732      dwLaceCnt=0;                                      // -> and we start to count the laces \r
733      dwLastLace=0;      \r
734      _ticks_since_last_update=0;\r
735      return;                                           // -> done, the next frame will get drawn\r
736     }\r
737 \r
738    bSkipNextFrame=FALSE;                               // init the frame skip signal to 'no skipping' first\r
739 \r
740    curticks = timeGetTime();\r
741    _ticks_since_last_update = curticks - lastticks;\r
742 \r
743    dwLastLace=dwLaceCnt;                               // store curr count (frame limitation helper)\r
744    dwWaitTime=dwLaceCnt*dwFrameRateTicks;              // calc the 'real psx lace time'\r
745 \r
746    if(_ticks_since_last_update>dwWaitTime)             // hey, we needed way too long for that frame...\r
747     {\r
748      if(bUseFrameLimit)                                // if limitation, we skip just next frame,\r
749       {                                                // and decide after, if we need to do more\r
750        iNumSkips=0;\r
751       }\r
752      else\r
753       {\r
754        iNumSkips=_ticks_since_last_update/dwWaitTime;  // -> calc number of frames to skip to catch up\r
755        iNumSkips--;                                    // -> since we already skip next frame, one down\r
756        if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP;        // -> well, somewhere we have to draw a line\r
757       }\r
758      bSkipNextFrame = TRUE;                            // -> signal for skipping the next frame\r
759     }\r
760    else                                                // we were faster than real psx? fine :)\r
761    if(bUseFrameLimit)                                  // frame limit used? so we wait til the 'real psx time' has been reached\r
762     {\r
763      if(dwLaceCnt>MAXLACE)                             // -> security check\r
764       _ticks_since_last_update=dwWaitTime;\r
765 \r
766      while(_ticks_since_last_update<dwWaitTime)        // just do a waiting loop...\r
767       {\r
768        curticks = timeGetTime();\r
769        _ticks_since_last_update = curticks - lastticks;\r
770       }\r
771     }\r
772 \r
773    lastticks = timeGetTime();\r
774   }\r
775 \r
776  dwLaceCnt=0;                                          // init lace counter\r
777 }\r
778 \r
779 //////////////////////////////////////////////////////////////////////// \r
780  \r
781 void calcfps(void) \r
782\r
783  static unsigned long curticks,_ticks_since_last_update,lastticks; \r
784  static long   fps_cnt = 0;\r
785  static unsigned long  fps_tck = 1; \r
786  static long           fpsskip_cnt = 0;\r
787  static unsigned long  fpsskip_tck = 1;\r
788  \r
789   { \r
790    curticks = timeGetTime(); \r
791    _ticks_since_last_update=curticks-lastticks; \r
792  \r
793    if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update) \r
794     fps_skip=min(fps_skip,((float)TIMEBASE/(float)_ticks_since_last_update+1.0f));\r
795  \r
796    lastticks = curticks; \r
797   } \r
798  \r
799  if(bUseFrameSkip && bUseFrameLimit)\r
800   {\r
801    fpsskip_tck += _ticks_since_last_update;\r
802 \r
803    if(++fpsskip_cnt==2)\r
804     {\r
805      fps_skip = (float)2000/(float)fpsskip_tck;\r
806 \r
807      fps_skip +=6.0f;\r
808 \r
809      fpsskip_cnt = 0;\r
810      fpsskip_tck = 1;\r
811     }\r
812   }\r
813 \r
814  fps_tck += _ticks_since_last_update; \r
815  \r
816  if(++fps_cnt==10) \r
817   { \r
818    fps_cur = (float)(TIMEBASE*10)/(float)fps_tck; \r
819 \r
820    fps_cnt = 0; \r
821    fps_tck = 1; \r
822  \r
823    if(bUseFrameLimit && fps_cur>fFrameRateHz)            // optical adjust ;) avoids flickering fps display \r
824     fps_cur=fFrameRateHz; \r
825   } \r
826\r
827 \r
828 void PCFrameCap (void) \r
829 {\r
830  static unsigned long curticks, lastticks, _ticks_since_last_update;\r
831  static unsigned long TicksToWait = 0;\r
832  bool Waiting = TRUE; \r
833  \r
834  while (Waiting) \r
835   {\r
836    curticks = timeGetTime(); \r
837    _ticks_since_last_update = curticks - lastticks; \r
838    if ((_ticks_since_last_update > TicksToWait) ||  \r
839        (curticks < lastticks)) \r
840     { \r
841      Waiting = FALSE; \r
842      lastticks = curticks; \r
843      TicksToWait = (TIMEBASE / (unsigned long)fFrameRateHz); \r
844     } \r
845   } \r
846\r
847  \r
848 //////////////////////////////////////////////////////////////////////// \r
849  \r
850 void PCcalcfps(void) \r
851\r
852  static unsigned long curticks,_ticks_since_last_update,lastticks; \r
853  static long  fps_cnt = 0; \r
854  static float fps_acc = 0;\r
855  float CurrentFPS=0;     \r
856   \r
857  curticks = timeGetTime(); \r
858  _ticks_since_last_update=curticks-lastticks;\r
859  if(_ticks_since_last_update) \r
860       CurrentFPS=(float)TIMEBASE/(float)_ticks_since_last_update;\r
861  else CurrentFPS = 0;\r
862  lastticks = curticks; \r
863  \r
864  fps_acc += CurrentFPS;\r
865 \r
866  if(++fps_cnt==10)\r
867   {\r
868    fps_cur = fps_acc / 10;\r
869    fps_acc = 0;\r
870    fps_cnt = 0;\r
871   }\r
872 \r
873  fps_skip=CurrentFPS+1.0f;\r
874 }\r
875 \r
876 ////////////////////////////////////////////////////////////////////////\r
877 \r
878 void SetAutoFrameCap(void)\r
879 {\r
880  if(iFrameLimit==1)\r
881   {\r
882    fFrameRateHz = fFrameRate;\r
883    dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz);\r
884    return;\r
885   }\r
886 \r
887  if(dwActFixes&128)\r
888   {\r
889    if (PSXDisplay.Interlaced)\r
890         fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f;\r
891    else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f;\r
892   }\r
893  else\r
894   {\r
895    //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f;\r
896 \r
897    if(PSXDisplay.PAL)\r
898     {\r
899      if (STATUSREG&GPUSTATUS_INTERLACED)\r
900            fFrameRateHz=33868800.0f/677343.75f;        // 50.00238\r
901       else fFrameRateHz=33868800.0f/680595.00f;        // 49.76351\r
902     }                                                     \r
903    else\r
904     {\r
905      if (STATUSREG&GPUSTATUS_INTERLACED)\r
906            fFrameRateHz=33868800.0f/565031.25f;        // 59.94146\r
907       else fFrameRateHz=33868800.0f/566107.50f;        // 59.82750\r
908     }\r
909 \r
910    dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz);\r
911   }\r
912 }\r
913 \r
914 ////////////////////////////////////////////////////////////////////////\r
915 \r
916 void SetFrameRateConfig(void)\r
917 {\r
918  if(!fFrameRate) fFrameRate=200.0f;\r
919 \r
920  if(fFrameRateHz==0) \r
921   {                                                    \r
922    if(iFrameLimit==2) fFrameRateHz=59.94f;             // auto framerate? set some init val (no pal/ntsc known yet)\r
923    else               fFrameRateHz=fFrameRate;         // else set user framerate\r
924   }\r
925 \r
926  dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz);\r
927 \r
928  if(iFrameLimit==2) SetAutoFrameCap();\r
929 }\r
930 \r
931 ////////////////////////////////////////////////////////////////////////\r
932 \r
933 void InitFrameCap(void)\r
934 {\r
935  // nothing on linux\r
936 }\r
937 \r
938 void ReInitFrameCap(void)\r
939 {\r
940  // nothing on linux\r
941 }\r
942 \r
943 ////////////////////////////////////////////////////////////////////////\r
944 \r
945 #endif\r
946 \r
947 ////////////////////////////////////////////////////////////////////////\r
948 \r
949 ////////////////////////////////////////////////////////////////////////\r
950 \r
951 void CheckFrameRate(void)                              // called in updatelace (on every emulated psx vsync)\r
952 {\r
953  if(bUseFrameSkip) \r
954   {\r
955    if(!(dwActFixes&0x100))\r
956     {\r
957      dwLaceCnt++;                                      // -> and store cnt of vsync between frames\r
958      if(dwLaceCnt>=MAXLACE && bUseFrameLimit) \r
959       {\r
960        if(dwLaceCnt==MAXLACE) bInitCap=TRUE;\r
961        FrameCap();\r
962       }\r
963     }\r
964    else if(bUseFrameLimit) FrameCap();\r
965    calcfps();                                          // -> calc fps display in skipping mode\r
966   }                                                  \r
967  else                                                  // -> non-skipping mode:\r
968   {\r
969    if(bUseFrameLimit) FrameCap();\r
970    calcfps();  \r
971   }\r
972 }\r
973 \r
974 ////////////////////////////////////////////////////////////////////////\r
975 \r
976 void CALLBACK GPUsetframelimit(unsigned long option)   // new EPSXE interface func: main emu can enable/disable fps limitation this way\r
977 {\r
978  bInitCap = TRUE;\r
979 \r
980  if(option==1)                                         // emu says: limit\r
981   {\r
982    bUseFrameLimit=TRUE;bUseFrameSkip=FALSE;iFrameLimit=2;\r
983    SetAutoFrameCap();\r
984   }\r
985  else                                                  // emu says: no limit\r
986   {\r
987    bUseFrameLimit=FALSE;\r
988   }\r
989 }\r
990 \r
991 ////////////////////////////////////////////////////////////////////////\r