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