147 lines
3.3 KiB
C++
147 lines
3.3 KiB
C++
/* FCE Ultra - NES/Famicom Emulator
|
|
*
|
|
* Copyright notice for this file:
|
|
* Copyright (C) 2002 Xodnizel
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
static uint64 tmethod,tfreq;
|
|
static uint64 desiredfps;
|
|
|
|
static int32 fps_scale_table[]=
|
|
{ 3, 3, 4, 8, 16, 32, 64, 128, 192, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 16384};
|
|
int32 fps_scale = 256;
|
|
|
|
static void RefreshThrottleFPS(void)
|
|
{
|
|
desiredfps=FCEUI_GetDesiredFPS()>>8;
|
|
desiredfps=(desiredfps*fps_scale)>>8;
|
|
}
|
|
|
|
static uint64 GetCurTime(void)
|
|
{
|
|
if(tmethod)
|
|
{
|
|
uint64 tmp;
|
|
|
|
/* Practically, LARGE_INTEGER and uint64 differ only by signness and name. */
|
|
QueryPerformanceCounter((LARGE_INTEGER*)&tmp);
|
|
|
|
return(tmp);
|
|
}
|
|
else
|
|
return((uint64)GetTickCount());
|
|
|
|
}
|
|
|
|
static void InitSpeedThrottle(void)
|
|
{
|
|
tmethod=0;
|
|
if(QueryPerformanceFrequency((LARGE_INTEGER*)&tfreq))
|
|
{
|
|
tmethod=1;
|
|
}
|
|
else
|
|
tfreq=1000;
|
|
tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */
|
|
}
|
|
|
|
|
|
static int SpeedThrottle(void)
|
|
{
|
|
static uint64 ttime,ltime;
|
|
|
|
waiter:
|
|
|
|
ttime=GetCurTime();
|
|
|
|
if( (ttime-ltime) < (tfreq/desiredfps) )
|
|
{
|
|
uint64 sleepy;
|
|
sleepy=(tfreq/desiredfps)-(ttime-ltime);
|
|
sleepy*=1000;
|
|
if(tfreq>=65536)
|
|
sleepy/=tfreq>>16;
|
|
else
|
|
sleepy=0;
|
|
if(sleepy>100)
|
|
{
|
|
// block for a max of 100ms to
|
|
// keep the gui responsive
|
|
Sleep(100);
|
|
return 1;
|
|
}
|
|
Sleep(sleepy);
|
|
goto waiter;
|
|
}
|
|
if( (ttime-ltime) >= (tfreq*4/desiredfps))
|
|
ltime=ttime;
|
|
else
|
|
{
|
|
ltime+=tfreq/desiredfps;
|
|
|
|
if( (ttime-ltime) >= (tfreq/desiredfps) ) // Oops, we're behind!
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
// Quick code for internal FPS display.
|
|
uint64 FCEUD_GetTime(void)
|
|
{
|
|
return(GetCurTime());
|
|
}
|
|
uint64 FCEUD_GetTimeFreq(void)
|
|
{
|
|
return(tfreq>>16);
|
|
}
|
|
|
|
static void IncreaseEmulationSpeed(void)
|
|
{
|
|
int i;
|
|
for(i=1; fps_scale_table[i]<fps_scale; i++)
|
|
;
|
|
fps_scale = fps_scale_table[i+1];
|
|
}
|
|
|
|
static void DecreaseEmulationSpeed(void)
|
|
{
|
|
int i;
|
|
for(i=1; fps_scale_table[i]<fps_scale; i++)
|
|
;
|
|
fps_scale = fps_scale_table[i-1];
|
|
}
|
|
|
|
#define fps_table_size (sizeof(fps_scale_table)/sizeof(fps_scale_table[0]))
|
|
|
|
void FCEUD_SetEmulationSpeed(int cmd)
|
|
{
|
|
switch(cmd)
|
|
{
|
|
case EMUSPEED_SLOWEST: fps_scale=fps_scale_table[0]; break;
|
|
case EMUSPEED_SLOWER: DecreaseEmulationSpeed(); break;
|
|
case EMUSPEED_NORMAL: fps_scale=256; break;
|
|
case EMUSPEED_FASTER: IncreaseEmulationSpeed(); break;
|
|
case EMUSPEED_FASTEST: fps_scale=fps_scale_table[fps_table_size-1]; break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
RefreshThrottleFPS();
|
|
|
|
FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
|
|
}
|