1 /***************************************************************************
\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
9 /***************************************************************************
\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
17 ***************************************************************************/
\r
19 //*************************************************************************//
\r
20 // History of changes:
\r
22 // 2009/03/08 - Pete
\r
23 // - generic cleanup for the Peops release
\r
25 //*************************************************************************//
\r
29 #include "Externals.h"
\r
34 #include "gpuStdafx.h"
\r
35 #include "gpuExternals.h"
\r
36 //#include "plugins.h"
\r
38 #include "gpuPrim.h"
\r
45 ////////////////////////////////////////////////////////////////////////
\r
47 ////////////////////////////////////////////////////////////////////////
\r
49 LARGE_INTEGER liCPUFrequency;
\r
52 ////////////////////////////////////////////////////////////////////////
\r
53 // FPS skipping / limit
\r
54 ////////////////////////////////////////////////////////////////////////
\r
56 BOOL bIsPerformanceCounter;
\r
58 DWORD dwFrameRateTicks;
\r
61 BOOL bUseFrameLimit;
\r
71 void FrameCap (void)
\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
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
89 if (bIsPerformanceCounter)
\r
90 QueryPerformanceCounter(&LastTime);
\r
91 lastticks = timeGetTime();
\r
96 //---------------------------------------------------------
\r
98 if(bIsPerformanceCounter)
\r
100 QueryPerformanceCounter(&CurrentTime);
\r
101 _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
\r
103 //---------------------------------------------------------
\r
104 // check if diff > 1/2 sec, if yes: take mm timer value
\r
105 //---------------------------------------------------------
\r
107 curticks = timeGetTime();
\r
108 if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))
\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
115 //---------------------------------------------------------
\r
117 if ((_ticks_since_last_update > TicksToWait) ||
\r
118 (CurrentTime.LowPart < LastTime.LowPart))
\r
120 LastTime.HighPart = CurrentTime.HighPart;
\r
121 LastTime.LowPart = CurrentTime.LowPart;
\r
123 lastticks=curticks;
\r
125 if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks)
\r
127 else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait);
\r
133 QueryPerformanceCounter(&CurrentTime);
\r
134 _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
\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
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
146 //---------------------------------------------------------
\r
148 if ((_ticks_since_last_update > TicksToWait) ||
\r
149 (CurrentTime.LowPart < LastTime.LowPart))
\r
153 lastticks=curticks;
\r
155 LastTime.HighPart = CurrentTime.HighPart;
\r
156 LastTime.LowPart = CurrentTime.LowPart;
\r
157 TicksToWait = dwFrameRateTicks;
\r
164 curticks = timeGetTime();
\r
165 _ticks_since_last_update = curticks - lastticks;
\r
167 if ((_ticks_since_last_update > TicksToWait) ||
\r
168 (curticks < lastticks))
\r
170 lastticks = curticks;
\r
172 if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks)
\r
174 else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait);
\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
186 lastticks = curticks;
\r
187 TicksToWait = dwFrameRateTicks;
\r
194 ////////////////////////////////////////////////////////////////////////
\r
196 #define MAXSKIP 120
\r
199 void FrameSkip(void)
\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
207 if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely
\r
209 if(iNumSkips) // we are in skipping mode?
\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
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
219 if(bInitCap || bSkipNextFrame) // first time or we skipped before?
\r
221 if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called?
\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
226 if(bIsPerformanceCounter) // -> now we calc the time of the last drawn frame + the time we spent skipping
\r
228 QueryPerformanceCounter(&CurrentTime);
\r
229 _ticks_since_last_update= dwT+CurrentTime.LowPart - LastTime.LowPart;
\r
233 curticks = timeGetTime();
\r
234 _ticks_since_last_update= dwT+curticks - lastticks;
\r
237 dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed
\r
239 if(_ticks_since_last_update<dwWaitTime) // -> we were too fast?
\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
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
249 QueryPerformanceCounter(&CurrentTime);
\r
250 _ticks_since_last_update = dwT+CurrentTime.LowPart - LastTime.LowPart;
\r
254 curticks = timeGetTime();
\r
255 _ticks_since_last_update = dwT+curticks - lastticks;
\r
259 else // we were still too slow ?!!?
\r
261 if(iAdditionalSkip<MAXSKIP) // -> well, somewhen we really have to stop skipping on very slow systems
\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
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
281 _ticks_since_last_update=0;
\r
282 return; // -> done, the next frame will get drawn
\r
285 bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first
\r
287 if(bIsPerformanceCounter) // get the current time (we are now at the end of one drawn frame)
\r
289 QueryPerformanceCounter(&CurrentTime);
\r
290 _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
\r
294 curticks = timeGetTime();
\r
295 _ticks_since_last_update = curticks - lastticks;
\r
298 dwLastLace=dwLaceCnt; // store curr count (frame limitation helper)
\r
299 dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time'
\r
301 if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame...
\r
303 if(bUseFrameLimit) // if limitation, we skip just next frame,
\r
304 { // and decide after, if we need to do more
\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
313 bSkipNextFrame = TRUE; // -> signal for skipping the next frame
\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
318 if(dwLaceCnt>MAXLACE) // -> security check
\r
319 _ticks_since_last_update=dwWaitTime;
\r
321 while(_ticks_since_last_update<dwWaitTime) // just do a waiting loop...
\r
323 if(bIsPerformanceCounter)
\r
325 QueryPerformanceCounter(&CurrentTime);
\r
326 _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
\r
330 curticks = timeGetTime();
\r
331 _ticks_since_last_update = curticks - lastticks;
\r
336 if(bIsPerformanceCounter) // ok, start time of the next frame
\r
337 QueryPerformanceCounter(&LastTime);
\r
338 lastticks = timeGetTime();
\r
341 dwLaceCnt=0; // init lace counter
\r
344 ////////////////////////////////////////////////////////////////////////
\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
356 if(bIsPerformanceCounter)
\r
358 QueryPerformanceCounter(&CurrentTime);
\r
359 _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart;
\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
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
371 LastTime.HighPart = CurrentTime.HighPart;
\r
372 LastTime.LowPart = CurrentTime.LowPart;
\r
376 curticks = timeGetTime();
\r
377 _ticks_since_last_update=curticks-lastticks;
\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
382 lastticks = curticks;
\r
385 if(bUseFrameSkip && bUseFrameLimit)
\r
387 fpsskip_tck += _ticks_since_last_update;
\r
389 if(++fpsskip_cnt==2)
\r
391 if(bIsPerformanceCounter)
\r
392 fps_skip = ((float)liCPUFrequency.LowPart) / ((float)fpsskip_tck) *2.0f;
\r
394 fps_skip = (float)2000/(float)fpsskip_tck;
\r
403 fps_tck += _ticks_since_last_update;
\r
407 if(bIsPerformanceCounter)
\r
408 fps_cur = ((float)liCPUFrequency.LowPart) / ((float)fps_tck) *10.0f;
\r
410 fps_cur = (float)10000/(float)fps_tck;
\r
415 if(bUseFrameLimit && fps_cur>fFrameRateHz) // optical adjust ;) avoids flickering fps display
\r
416 fps_cur=fFrameRateHz;
\r
420 ////////////////////////////////////////////////////////////////////////
\r
421 // PC FPS skipping / limit
\r
422 ////////////////////////////////////////////////////////////////////////
\r
424 void PCFrameCap(void)
\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
434 if(bIsPerformanceCounter)
\r
436 QueryPerformanceCounter(&CurrentTime);
\r
437 _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart;
\r
439 //------------------------------------------------//
\r
440 curticks = timeGetTime();
\r
441 if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1))
\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
447 //------------------------------------------------//
\r
449 if ((_ticks_since_last_update > TicksToWait) ||
\r
450 (CurrentTime.LowPart < LastTime.LowPart))
\r
454 lastticks=curticks;
\r
456 LastTime.HighPart = CurrentTime.HighPart;
\r
457 LastTime.LowPart = CurrentTime.LowPart;
\r
458 TicksToWait = (liCPUFrequency.LowPart / fFrameRateHz);
\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
469 lastticks = curticks;
\r
470 TicksToWait = (1000 / (DWORD)fFrameRateHz);
\r
476 ////////////////////////////////////////////////////////////////////////
\r
478 void PCcalcfps(void)
\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
487 if(bIsPerformanceCounter)
\r
489 QueryPerformanceCounter(&CurrentTime);
\r
490 _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart;
\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
499 if(_ticks_since_last_update)
\r
501 CurrentFPS = ((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update);
\r
503 else CurrentFPS = 0;
\r
504 LastTime.HighPart = CurrentTime.HighPart;
\r
505 LastTime.LowPart = CurrentTime.LowPart;
\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
516 fps_acc += CurrentFPS;
\r
520 fps_cur = fps_acc / 10;
\r
525 fps_skip=CurrentFPS+1.0f;
\r
528 ////////////////////////////////////////////////////////////////////////
\r
530 void SetAutoFrameCap(void)
\r
534 fFrameRateHz = fFrameRate;
\r
535 if(bIsPerformanceCounter)
\r
536 dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz);
\r
537 else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz);
\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
549 //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f;
\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
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
564 if(bIsPerformanceCounter)
\r
565 dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz);
\r
566 else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz);
\r
570 ////////////////////////////////////////////////////////////////////////
\r
572 void InitFrameCap(void) // inits cpu frequency info (on gpu startup)
\r
574 if (QueryPerformanceFrequency (&liCPUFrequency))
\r
575 bIsPerformanceCounter = TRUE;
\r
576 else bIsPerformanceCounter = FALSE;
\r
579 ////////////////////////////////////////////////////////////////////////
\r
581 void ReInitFrameCap(void)
\r
583 BOOL bOldPerformanceCounter=bIsPerformanceCounter; // store curr timer mode
\r
585 if(dwActFixes&0x10000) // check game fix... high performance counters are bad on some mb chipsets
\r
586 bIsPerformanceCounter=FALSE;
\r
589 if (QueryPerformanceFrequency (&liCPUFrequency))
\r
590 bIsPerformanceCounter = TRUE;
\r
591 else bIsPerformanceCounter = FALSE;
\r
594 if(bOldPerformanceCounter!=bIsPerformanceCounter) // changed?
\r
601 ////////////////////////////////////////////////////////////////////////
\r
603 void SetFrameRateConfig(void)
\r
605 if(fFrameRateHz==0)
\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
611 if(bIsPerformanceCounter)
\r
612 dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz);
\r
613 else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz);
\r
616 ////////////////////////////////////////////////////////////////////////
\r
618 // LINUX ---------------------------------------------
\r
622 #define TIMEBASE 100000
\r
624 // hehehe... using same func name as with win32 ;) wow, are we genius ;)
\r
625 unsigned long timeGetTime()
\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
632 void FrameCap(void)
\r
634 static unsigned long curticks, lastticks, _ticks_since_last_update;
\r
635 static unsigned long TicksToWait = 0;
\r
636 bool Waiting = TRUE;
\r
639 curticks = timeGetTime();
\r
640 _ticks_since_last_update = curticks - lastticks;
\r
642 if((_ticks_since_last_update > TicksToWait) ||
\r
643 (curticks <lastticks))
\r
645 lastticks = curticks;
\r
647 if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks)
\r
649 else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait);
\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
661 lastticks = curticks;
\r
662 TicksToWait = dwFrameRateTicks;
\r
669 ////////////////////////////////////////////////////////////////////////
\r
671 #define MAXSKIP 120
\r
674 void FrameSkip(void)
\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
680 if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely
\r
682 if(iNumSkips) // we are in skipping mode?
\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
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
692 if(bInitCap || bSkipNextFrame) // first time or we skipped before?
\r
694 if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called?
\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
699 curticks = timeGetTime();
\r
700 _ticks_since_last_update= dwT+curticks - lastticks;
\r
702 dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed
\r
704 if(_ticks_since_last_update<dwWaitTime) // -> we were too fast?
\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
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
716 else // we were still too slow ?!!?
\r
718 if(iAdditionalSkip<MAXSKIP) // -> well, somewhen we really have to stop skipping on very slow systems
\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
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
734 _ticks_since_last_update=0;
\r
735 return; // -> done, the next frame will get drawn
\r
738 bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first
\r
740 curticks = timeGetTime();
\r
741 _ticks_since_last_update = curticks - lastticks;
\r
743 dwLastLace=dwLaceCnt; // store curr count (frame limitation helper)
\r
744 dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time'
\r
746 if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame...
\r
748 if(bUseFrameLimit) // if limitation, we skip just next frame,
\r
749 { // and decide after, if we need to do more
\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
758 bSkipNextFrame = TRUE; // -> signal for skipping the next frame
\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
763 if(dwLaceCnt>MAXLACE) // -> security check
\r
764 _ticks_since_last_update=dwWaitTime;
\r
766 while(_ticks_since_last_update<dwWaitTime) // just do a waiting loop...
\r
768 curticks = timeGetTime();
\r
769 _ticks_since_last_update = curticks - lastticks;
\r
773 lastticks = timeGetTime();
\r
776 dwLaceCnt=0; // init lace counter
\r
779 ////////////////////////////////////////////////////////////////////////
\r
781 void calcfps(void)
\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
790 curticks = timeGetTime();
\r
791 _ticks_since_last_update=curticks-lastticks;
\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
796 lastticks = curticks;
\r
799 if(bUseFrameSkip && bUseFrameLimit)
\r
801 fpsskip_tck += _ticks_since_last_update;
\r
803 if(++fpsskip_cnt==2)
\r
805 fps_skip = (float)2000/(float)fpsskip_tck;
\r
814 fps_tck += _ticks_since_last_update;
\r
818 fps_cur = (float)(TIMEBASE*10)/(float)fps_tck;
\r
823 if(bUseFrameLimit && fps_cur>fFrameRateHz) // optical adjust ;) avoids flickering fps display
\r
824 fps_cur=fFrameRateHz;
\r
828 void PCFrameCap (void)
\r
830 static unsigned long curticks, lastticks, _ticks_since_last_update;
\r
831 static unsigned long TicksToWait = 0;
\r
832 bool Waiting = TRUE;
\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
842 lastticks = curticks;
\r
843 TicksToWait = (TIMEBASE / (unsigned long)fFrameRateHz);
\r
848 ////////////////////////////////////////////////////////////////////////
\r
850 void PCcalcfps(void)
\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
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
864 fps_acc += CurrentFPS;
\r
868 fps_cur = fps_acc / 10;
\r
873 fps_skip=CurrentFPS+1.0f;
\r
876 ////////////////////////////////////////////////////////////////////////
\r
878 void SetAutoFrameCap(void)
\r
882 fFrameRateHz = fFrameRate;
\r
883 dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz);
\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
895 //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f;
\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
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
910 dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz);
\r
914 ////////////////////////////////////////////////////////////////////////
\r
916 void SetFrameRateConfig(void)
\r
918 if(!fFrameRate) fFrameRate=200.0f;
\r
920 if(fFrameRateHz==0)
\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
926 dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz);
\r
928 if(iFrameLimit==2) SetAutoFrameCap();
\r
931 ////////////////////////////////////////////////////////////////////////
\r
933 void InitFrameCap(void)
\r
935 // nothing on linux
\r
938 void ReInitFrameCap(void)
\r
940 // nothing on linux
\r
943 ////////////////////////////////////////////////////////////////////////
\r
947 ////////////////////////////////////////////////////////////////////////
\r
949 ////////////////////////////////////////////////////////////////////////
\r
951 void CheckFrameRate(void) // called in updatelace (on every emulated psx vsync)
\r
955 if(!(dwActFixes&0x100))
\r
957 dwLaceCnt++; // -> and store cnt of vsync between frames
\r
958 if(dwLaceCnt>=MAXLACE && bUseFrameLimit)
\r
960 if(dwLaceCnt==MAXLACE) bInitCap=TRUE;
\r
964 else if(bUseFrameLimit) FrameCap();
\r
965 calcfps(); // -> calc fps display in skipping mode
\r
967 else // -> non-skipping mode:
\r
969 if(bUseFrameLimit) FrameCap();
\r
974 ////////////////////////////////////////////////////////////////////////
\r
976 void CALLBACK GPUsetframelimit(unsigned long option) // new EPSXE interface func: main emu can enable/disable fps limitation this way
\r
980 if(option==1) // emu says: limit
\r
982 bUseFrameLimit=TRUE;bUseFrameSkip=FALSE;iFrameLimit=2;
\r
985 else // emu says: no limit
\r
987 bUseFrameLimit=FALSE;
\r
991 ////////////////////////////////////////////////////////////////////////
\r