Merge pull request #247 from mjbudd77/master
Frame Timing and Thread Scheduling Enhancements for Qt GUI
This commit is contained in:
commit
3ccbc61aa1
|
@ -430,6 +430,7 @@ set(SRC_DRIVERS_SDL
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/InputConf.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/InputConf.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GamePadConf.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GamePadConf.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HotKeyConf.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HotKeyConf.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TimingConf.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/PaletteConf.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/PaletteConf.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GuiConf.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GuiConf.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MoviePlay.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MoviePlay.cpp
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
// GameApp.cpp
|
// GameApp.cpp
|
||||||
//
|
//
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -27,6 +36,7 @@
|
||||||
#include "Qt/GuiConf.h"
|
#include "Qt/GuiConf.h"
|
||||||
#include "Qt/MoviePlay.h"
|
#include "Qt/MoviePlay.h"
|
||||||
#include "Qt/MovieOptions.h"
|
#include "Qt/MovieOptions.h"
|
||||||
|
#include "Qt/TimingConf.h"
|
||||||
#include "Qt/LuaControl.h"
|
#include "Qt/LuaControl.h"
|
||||||
#include "Qt/CheatsConf.h"
|
#include "Qt/CheatsConf.h"
|
||||||
#include "Qt/GameGenie.h"
|
#include "Qt/GameGenie.h"
|
||||||
|
@ -50,6 +60,7 @@
|
||||||
consoleWin_t::consoleWin_t(QWidget *parent)
|
consoleWin_t::consoleWin_t(QWidget *parent)
|
||||||
: QMainWindow( parent )
|
: QMainWindow( parent )
|
||||||
{
|
{
|
||||||
|
int opt;
|
||||||
int use_SDL_video = false;
|
int use_SDL_video = false;
|
||||||
int setFullScreen = false;
|
int setFullScreen = false;
|
||||||
|
|
||||||
|
@ -95,11 +106,24 @@ consoleWin_t::consoleWin_t(QWidget *parent)
|
||||||
connect( gameTimer, &QTimer::timeout, this, &consoleWin_t::updatePeriodic );
|
connect( gameTimer, &QTimer::timeout, this, &consoleWin_t::updatePeriodic );
|
||||||
|
|
||||||
gameTimer->setTimerType( Qt::PreciseTimer );
|
gameTimer->setTimerType( Qt::PreciseTimer );
|
||||||
//gameTimer->start( 16 ); // 60hz
|
|
||||||
gameTimer->start( 8 ); // 120hz
|
gameTimer->start( 8 ); // 120hz
|
||||||
|
|
||||||
emulatorThread->start();
|
emulatorThread->start();
|
||||||
|
|
||||||
|
g_config->getOption( "SDL.SetSchedParam", &opt );
|
||||||
|
|
||||||
|
if ( opt )
|
||||||
|
{
|
||||||
|
int policy, prio, nice;
|
||||||
|
|
||||||
|
g_config->getOption( "SDL.GuiSchedPolicy", &policy );
|
||||||
|
g_config->getOption( "SDL.GuiSchedPrioRt", &prio );
|
||||||
|
g_config->getOption( "SDL.GuiSchedNice" , &nice );
|
||||||
|
|
||||||
|
setNicePriority( nice );
|
||||||
|
|
||||||
|
setSchedParam( policy, prio );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
consoleWin_t::~consoleWin_t(void)
|
consoleWin_t::~consoleWin_t(void)
|
||||||
|
@ -404,6 +428,14 @@ void consoleWin_t::createMainMenu(void)
|
||||||
|
|
||||||
optMenu->addAction(guiConfig);
|
optMenu->addAction(guiConfig);
|
||||||
|
|
||||||
|
// Options -> Timing Config
|
||||||
|
timingConfig = new QAction(tr("Timing Config"), this);
|
||||||
|
//timingConfig->setShortcut( QKeySequence(tr("Ctrl+C")));
|
||||||
|
timingConfig->setStatusTip(tr("Timing Configure"));
|
||||||
|
connect(timingConfig, SIGNAL(triggered()), this, SLOT(openTimingConfWin(void)) );
|
||||||
|
|
||||||
|
optMenu->addAction(timingConfig);
|
||||||
|
|
||||||
// Options -> Movie Options
|
// Options -> Movie Options
|
||||||
movieConfig = new QAction(tr("Movie Options"), this);
|
movieConfig = new QAction(tr("Movie Options"), this);
|
||||||
//movieConfig->setShortcut( QKeySequence(tr("Ctrl+C")));
|
//movieConfig->setShortcut( QKeySequence(tr("Ctrl+C")));
|
||||||
|
@ -1252,6 +1284,17 @@ void consoleWin_t::openGuiConfWin(void)
|
||||||
guiConfWin->show();
|
guiConfWin->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void consoleWin_t::openTimingConfWin(void)
|
||||||
|
{
|
||||||
|
TimingConfDialog_t *tmConfWin;
|
||||||
|
|
||||||
|
//printf("Open Timing Config Window\n");
|
||||||
|
|
||||||
|
tmConfWin = new TimingConfDialog_t(this);
|
||||||
|
|
||||||
|
tmConfWin->show();
|
||||||
|
}
|
||||||
|
|
||||||
void consoleWin_t::openMovieOptWin(void)
|
void consoleWin_t::openMovieOptWin(void)
|
||||||
{
|
{
|
||||||
MovieOptionsDialog_t *win;
|
MovieOptionsDialog_t *win;
|
||||||
|
@ -1770,6 +1813,159 @@ void consoleWin_t::aboutQt(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int consoleWin_t::setNicePriority( int value )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#if defined(__linux__)
|
||||||
|
|
||||||
|
if ( value < -20 )
|
||||||
|
{
|
||||||
|
value = -20;
|
||||||
|
}
|
||||||
|
else if ( value > 19 )
|
||||||
|
{
|
||||||
|
value = 19;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ::setpriority( PRIO_PROCESS, getpid(), value ) )
|
||||||
|
{
|
||||||
|
perror("Emulator thread setpriority error: ");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
|
||||||
|
if ( value < -20 )
|
||||||
|
{
|
||||||
|
value = -20;
|
||||||
|
}
|
||||||
|
else if ( value > 20 )
|
||||||
|
{
|
||||||
|
value = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ::setpriority( PRIO_PROCESS, getpid(), value ) )
|
||||||
|
{
|
||||||
|
perror("Emulator thread setpriority error: ");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int consoleWin_t::getNicePriority(void)
|
||||||
|
{
|
||||||
|
return ::getpriority( PRIO_PROCESS, getpid() );
|
||||||
|
}
|
||||||
|
|
||||||
|
int consoleWin_t::getMinSchedPriority(void)
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
|
||||||
|
if ( getSchedParam( policy, prio ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return sched_get_priority_min( policy );
|
||||||
|
}
|
||||||
|
|
||||||
|
int consoleWin_t::getMaxSchedPriority(void)
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
|
||||||
|
if ( getSchedParam( policy, prio ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return sched_get_priority_max( policy );
|
||||||
|
}
|
||||||
|
|
||||||
|
int consoleWin_t::getSchedParam( int &policy, int &priority )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
struct sched_param p;
|
||||||
|
|
||||||
|
policy = sched_getscheduler( getpid() );
|
||||||
|
|
||||||
|
if ( sched_getparam( getpid(), &p ) )
|
||||||
|
{
|
||||||
|
perror("GUI thread sched_getparam error: ");
|
||||||
|
ret = -1;
|
||||||
|
priority = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priority = p.sched_priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
struct sched_param p;
|
||||||
|
|
||||||
|
if ( pthread_getschedparam( pthread_self(), &policy, &p ) )
|
||||||
|
{
|
||||||
|
perror("GUI thread pthread_getschedparam error: ");
|
||||||
|
ret = -1;
|
||||||
|
priority = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priority = p.sched_priority;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int consoleWin_t::setSchedParam( int policy, int priority )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#if defined(__linux__)
|
||||||
|
struct sched_param p;
|
||||||
|
int minPrio, maxPrio;
|
||||||
|
|
||||||
|
minPrio = sched_get_priority_min( policy );
|
||||||
|
maxPrio = sched_get_priority_max( policy );
|
||||||
|
|
||||||
|
if ( priority < minPrio )
|
||||||
|
{
|
||||||
|
priority = minPrio;
|
||||||
|
}
|
||||||
|
else if ( priority > maxPrio )
|
||||||
|
{
|
||||||
|
priority = maxPrio;
|
||||||
|
}
|
||||||
|
p.sched_priority = priority;
|
||||||
|
|
||||||
|
if ( sched_setscheduler( getpid(), policy, &p ) )
|
||||||
|
{
|
||||||
|
perror("GUI thread sched_setscheduler error");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
struct sched_param p;
|
||||||
|
int minPrio, maxPrio;
|
||||||
|
|
||||||
|
minPrio = sched_get_priority_min( policy );
|
||||||
|
maxPrio = sched_get_priority_max( policy );
|
||||||
|
|
||||||
|
if ( priority < minPrio )
|
||||||
|
{
|
||||||
|
priority = minPrio;
|
||||||
|
}
|
||||||
|
else if ( priority > maxPrio )
|
||||||
|
{
|
||||||
|
priority = maxPrio;
|
||||||
|
}
|
||||||
|
p.sched_priority = priority;
|
||||||
|
|
||||||
|
if ( ::pthread_setschedparam( pthread_self(), policy, &p ) != 0 )
|
||||||
|
{
|
||||||
|
perror("GUI thread pthread_setschedparam error: ");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void consoleWin_t::syncActionConfig( QAction *act, const char *property )
|
void consoleWin_t::syncActionConfig( QAction *act, const char *property )
|
||||||
{
|
{
|
||||||
if ( act->isCheckable() )
|
if ( act->isCheckable() )
|
||||||
|
@ -1821,11 +2017,205 @@ void consoleWin_t::updatePeriodic(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emulatorThread_t::emulatorThread_t(void)
|
||||||
|
{
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
pself = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#ifndef SYS_gettid
|
||||||
|
#error "SYS_gettid unavailable on this system"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define gettid() ((pid_t)syscall(SYS_gettid))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void emulatorThread_t::init(void)
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
if ( pthread_self() == (pthread_t)QThread::currentThreadId() )
|
||||||
|
{
|
||||||
|
pself = pthread_self();
|
||||||
|
//printf("EMU is using PThread: %p\n", (void*)pself);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
pid = gettid();
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
pid = getpid();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_config->getOption( "SDL.SetSchedParam", &opt );
|
||||||
|
|
||||||
|
if ( opt )
|
||||||
|
{
|
||||||
|
int policy, prio, nice;
|
||||||
|
|
||||||
|
g_config->getOption( "SDL.EmuSchedPolicy", &policy );
|
||||||
|
g_config->getOption( "SDL.EmuSchedPrioRt", &prio );
|
||||||
|
g_config->getOption( "SDL.EmuSchedNice" , &nice );
|
||||||
|
|
||||||
|
setNicePriority( nice );
|
||||||
|
|
||||||
|
setSchedParam( policy, prio );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void emulatorThread_t::setPriority( QThread::Priority priority_req )
|
||||||
|
{
|
||||||
|
//printf("New Priority: %i \n", priority_req );
|
||||||
|
//printf("Old Priority: %i \n", priority() );
|
||||||
|
|
||||||
|
QThread::setPriority( priority_req );
|
||||||
|
|
||||||
|
//printf("Set Priority: %i \n", priority() );
|
||||||
|
}
|
||||||
|
|
||||||
|
int emulatorThread_t::setNicePriority( int value )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#if defined(__linux__)
|
||||||
|
|
||||||
|
if ( value < -20 )
|
||||||
|
{
|
||||||
|
value = -20;
|
||||||
|
}
|
||||||
|
else if ( value > 19 )
|
||||||
|
{
|
||||||
|
value = 19;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ::setpriority( PRIO_PROCESS, pid, value ) )
|
||||||
|
{
|
||||||
|
perror("Emulator thread setpriority error: ");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
|
||||||
|
if ( value < -20 )
|
||||||
|
{
|
||||||
|
value = -20;
|
||||||
|
}
|
||||||
|
else if ( value > 20 )
|
||||||
|
{
|
||||||
|
value = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ::setpriority( PRIO_PROCESS, pid, value ) )
|
||||||
|
{
|
||||||
|
perror("Emulator thread setpriority error: ");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emulatorThread_t::getNicePriority(void)
|
||||||
|
{
|
||||||
|
return ::getpriority( PRIO_PROCESS, pid );
|
||||||
|
}
|
||||||
|
|
||||||
|
int emulatorThread_t::getMinSchedPriority(void)
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
|
||||||
|
if ( getSchedParam( policy, prio ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return sched_get_priority_min( policy );
|
||||||
|
}
|
||||||
|
|
||||||
|
int emulatorThread_t::getMaxSchedPriority(void)
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
|
||||||
|
if ( getSchedParam( policy, prio ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return sched_get_priority_max( policy );
|
||||||
|
}
|
||||||
|
|
||||||
|
int emulatorThread_t::getSchedParam( int &policy, int &priority )
|
||||||
|
{
|
||||||
|
struct sched_param p;
|
||||||
|
|
||||||
|
if ( pthread_getschedparam( pself, &policy, &p ) )
|
||||||
|
{
|
||||||
|
perror("Emulator thread pthread_getschedparam error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
priority = p.sched_priority;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emulatorThread_t::setSchedParam( int policy, int priority )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#if defined(__linux__)
|
||||||
|
struct sched_param p;
|
||||||
|
int minPrio, maxPrio;
|
||||||
|
|
||||||
|
minPrio = sched_get_priority_min( policy );
|
||||||
|
maxPrio = sched_get_priority_max( policy );
|
||||||
|
|
||||||
|
if ( priority < minPrio )
|
||||||
|
{
|
||||||
|
priority = minPrio;
|
||||||
|
}
|
||||||
|
else if ( priority > maxPrio )
|
||||||
|
{
|
||||||
|
priority = maxPrio;
|
||||||
|
}
|
||||||
|
p.sched_priority = priority;
|
||||||
|
|
||||||
|
if ( ::pthread_setschedparam( pself, policy, &p ) != 0 )
|
||||||
|
{
|
||||||
|
perror("Emulator thread pthread_setschedparam error: ");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
struct sched_param p;
|
||||||
|
int minPrio, maxPrio;
|
||||||
|
|
||||||
|
minPrio = sched_get_priority_min( policy );
|
||||||
|
maxPrio = sched_get_priority_max( policy );
|
||||||
|
|
||||||
|
if ( priority < minPrio )
|
||||||
|
{
|
||||||
|
priority = minPrio;
|
||||||
|
}
|
||||||
|
else if ( priority > maxPrio )
|
||||||
|
{
|
||||||
|
priority = maxPrio;
|
||||||
|
}
|
||||||
|
p.sched_priority = priority;
|
||||||
|
|
||||||
|
if ( ::pthread_setschedparam( pself, policy, &p ) != 0 )
|
||||||
|
{
|
||||||
|
perror("Emulator thread pthread_setschedparam error: ");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void emulatorThread_t::run(void)
|
void emulatorThread_t::run(void)
|
||||||
{
|
{
|
||||||
printf("Emulator Start\n");
|
printf("Emulator Start\n");
|
||||||
nes_shm->runEmulator = 1;
|
nes_shm->runEmulator = 1;
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
while ( nes_shm->runEmulator )
|
while ( nes_shm->runEmulator )
|
||||||
{
|
{
|
||||||
fceuWrapperUpdate();
|
fceuWrapperUpdate();
|
||||||
|
|
|
@ -28,10 +28,32 @@ class emulatorThread_t : public QThread
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
//public slots:
|
protected:
|
||||||
void run( void ) override;
|
void run( void ) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
emulatorThread_t(void);
|
||||||
|
|
||||||
|
void setPriority( QThread::Priority priority );
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
int setSchedParam( int policy, int priority );
|
||||||
|
int getSchedParam( int &policy, int &priority );
|
||||||
|
int setNicePriority( int value );
|
||||||
|
int getNicePriority( void );
|
||||||
|
int getMinSchedPriority(void);
|
||||||
|
int getMaxSchedPriority(void);
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
void init(void);
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
pthread_t pself;
|
||||||
|
int pid;
|
||||||
|
#endif
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished();
|
void finished();
|
||||||
};
|
};
|
||||||
|
|
||||||
class consoleWin_t : public QMainWindow
|
class consoleWin_t : public QMainWindow
|
||||||
|
@ -53,6 +75,17 @@ class consoleWin_t : public QMainWindow
|
||||||
|
|
||||||
int showListSelectDialog( const char *title, std::vector <std::string> &l );
|
int showListSelectDialog( const char *title, std::vector <std::string> &l );
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
int setSchedParam( int policy, int priority );
|
||||||
|
int getSchedParam( int &policy, int &priority );
|
||||||
|
int setNicePriority( int value );
|
||||||
|
int getNicePriority( void );
|
||||||
|
int getMinSchedPriority(void);
|
||||||
|
int getMaxSchedPriority(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
emulatorThread_t *emulatorThread;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QMenu *fileMenu;
|
QMenu *fileMenu;
|
||||||
QMenu *optMenu;
|
QMenu *optMenu;
|
||||||
|
@ -78,6 +111,7 @@ class consoleWin_t : public QMainWindow
|
||||||
QAction *hotkeyConfig;
|
QAction *hotkeyConfig;
|
||||||
QAction *paletteConfig;
|
QAction *paletteConfig;
|
||||||
QAction *guiConfig;
|
QAction *guiConfig;
|
||||||
|
QAction *timingConfig;
|
||||||
QAction *movieConfig;
|
QAction *movieConfig;
|
||||||
QAction *autoResume;
|
QAction *autoResume;
|
||||||
QAction *fullscreen;
|
QAction *fullscreen;
|
||||||
|
@ -112,8 +146,6 @@ class consoleWin_t : public QMainWindow
|
||||||
|
|
||||||
QTimer *gameTimer;
|
QTimer *gameTimer;
|
||||||
|
|
||||||
emulatorThread_t *emulatorThread;
|
|
||||||
|
|
||||||
std::string errorMsg;
|
std::string errorMsg;
|
||||||
bool errorMsgValid;
|
bool errorMsgValid;
|
||||||
|
|
||||||
|
@ -148,6 +180,7 @@ class consoleWin_t : public QMainWindow
|
||||||
void openHotkeyConfWin(void);
|
void openHotkeyConfWin(void);
|
||||||
void openPaletteConfWin(void);
|
void openPaletteConfWin(void);
|
||||||
void openGuiConfWin(void);
|
void openGuiConfWin(void);
|
||||||
|
void openTimingConfWin(void);
|
||||||
void openMovieOptWin(void);
|
void openMovieOptWin(void);
|
||||||
void openCodeDataLogger(void);
|
void openCodeDataLogger(void);
|
||||||
void openTraceLogger(void);
|
void openTraceLogger(void);
|
||||||
|
|
|
@ -0,0 +1,534 @@
|
||||||
|
// TimingConf.cpp
|
||||||
|
//
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
|
||||||
|
#include "Qt/main.h"
|
||||||
|
#include "Qt/dface.h"
|
||||||
|
#include "Qt/input.h"
|
||||||
|
#include "Qt/config.h"
|
||||||
|
#include "Qt/keyscan.h"
|
||||||
|
#include "Qt/throttle.h"
|
||||||
|
#include "Qt/fceuWrapper.h"
|
||||||
|
#include "Qt/ConsoleWindow.h"
|
||||||
|
#include "Qt/TimingConf.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
static bool hasNicePermissions( int val )
|
||||||
|
{
|
||||||
|
int usrID;
|
||||||
|
bool usrRoot;
|
||||||
|
|
||||||
|
usrID = geteuid();
|
||||||
|
|
||||||
|
usrRoot = (usrID == 0);
|
||||||
|
|
||||||
|
if ( usrRoot )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#ifdef __linux__
|
||||||
|
struct rlimit r;
|
||||||
|
|
||||||
|
if ( getrlimit( RLIMIT_NICE, &r ) == 0 )
|
||||||
|
{
|
||||||
|
int ncur = 20 - r.rlim_cur;
|
||||||
|
|
||||||
|
if ( val >= ncur )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//printf("RLim Cur: %lu \n", r.rlim_cur );
|
||||||
|
//printf("RLim Max: %lu \n", r.rlim_max );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
TimingConfDialog_t::TimingConfDialog_t(QWidget *parent)
|
||||||
|
: QDialog( parent )
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
QVBoxLayout *mainLayout;
|
||||||
|
QHBoxLayout *hbox;
|
||||||
|
QGridLayout *grid;
|
||||||
|
QGroupBox *emuPrioBox, *guiPrioBox;
|
||||||
|
|
||||||
|
setWindowTitle("Timing Configuration");
|
||||||
|
|
||||||
|
mainLayout = new QVBoxLayout();
|
||||||
|
|
||||||
|
emuPrioCtlEna = new QCheckBox( tr("Set Scheduling Parameters at Startup") );
|
||||||
|
|
||||||
|
emuPrioBox = new QGroupBox( tr("EMU Thread Scheduling Parameters") );
|
||||||
|
guiPrioBox = new QGroupBox( tr("GUI Thread Scheduling Parameters") );
|
||||||
|
grid = new QGridLayout();
|
||||||
|
emuPrioBox->setLayout( grid );
|
||||||
|
|
||||||
|
emuSchedPolicyBox = new QComboBox();
|
||||||
|
emuSchedPrioSlider = new QSlider( Qt::Horizontal );
|
||||||
|
emuSchedNiceSlider = new QSlider( Qt::Horizontal );
|
||||||
|
emuSchedPrioLabel = new QLabel( tr("Priority (RT)") );
|
||||||
|
emuSchedNiceLabel = new QLabel( tr("Priority (Nice)") );
|
||||||
|
|
||||||
|
emuSchedPolicyBox->addItem( tr("SCHED_OTHER") , SCHED_OTHER );
|
||||||
|
emuSchedPolicyBox->addItem( tr("SCHED_FIFO") , SCHED_FIFO );
|
||||||
|
emuSchedPolicyBox->addItem( tr("SCHED_RR") , SCHED_RR );
|
||||||
|
|
||||||
|
grid->addWidget( new QLabel( tr("Policy") ), 0, 0 );
|
||||||
|
grid->addWidget( emuSchedPolicyBox, 0, 1 );
|
||||||
|
grid->addWidget( emuSchedPrioLabel, 1, 0 );
|
||||||
|
grid->addWidget( emuSchedPrioSlider, 1, 1 );
|
||||||
|
grid->addWidget( emuSchedNiceLabel, 2, 0 );
|
||||||
|
grid->addWidget( emuSchedNiceSlider, 2, 1 );
|
||||||
|
|
||||||
|
mainLayout->addWidget( emuPrioCtlEna );
|
||||||
|
mainLayout->addWidget( emuPrioBox );
|
||||||
|
|
||||||
|
grid = new QGridLayout();
|
||||||
|
guiPrioBox->setLayout( grid );
|
||||||
|
|
||||||
|
guiSchedPolicyBox = new QComboBox();
|
||||||
|
guiSchedPrioSlider = new QSlider( Qt::Horizontal );
|
||||||
|
guiSchedNiceSlider = new QSlider( Qt::Horizontal );
|
||||||
|
guiSchedPrioLabel = new QLabel( tr("Priority (RT)") );
|
||||||
|
guiSchedNiceLabel = new QLabel( tr("Priority (Nice)") );
|
||||||
|
|
||||||
|
guiSchedPolicyBox->addItem( tr("SCHED_OTHER") , SCHED_OTHER );
|
||||||
|
guiSchedPolicyBox->addItem( tr("SCHED_FIFO") , SCHED_FIFO );
|
||||||
|
guiSchedPolicyBox->addItem( tr("SCHED_RR") , SCHED_RR );
|
||||||
|
|
||||||
|
grid->addWidget( new QLabel( tr("Policy") ), 0, 0 );
|
||||||
|
grid->addWidget( guiSchedPolicyBox, 0, 1 );
|
||||||
|
grid->addWidget( guiSchedPrioLabel, 1, 0 );
|
||||||
|
grid->addWidget( guiSchedPrioSlider, 1, 1 );
|
||||||
|
grid->addWidget( guiSchedNiceLabel, 2, 0 );
|
||||||
|
grid->addWidget( guiSchedNiceSlider, 2, 1 );
|
||||||
|
|
||||||
|
mainLayout->addWidget( guiPrioBox );
|
||||||
|
|
||||||
|
hbox = new QHBoxLayout();
|
||||||
|
timingDevSelBox = new QComboBox();
|
||||||
|
timingDevSelBox->addItem( tr("NanoSleep") , 0 );
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
timingDevSelBox->addItem( tr("Timer FD") , 1 );
|
||||||
|
#endif
|
||||||
|
hbox->addWidget( new QLabel( tr("Timing Mechanism:") ) );
|
||||||
|
hbox->addWidget( timingDevSelBox );
|
||||||
|
mainLayout->addLayout( hbox );
|
||||||
|
|
||||||
|
setLayout( mainLayout );
|
||||||
|
|
||||||
|
g_config->getOption( "SDL.SetSchedParam", &opt );
|
||||||
|
|
||||||
|
emuPrioCtlEna->setChecked( opt );
|
||||||
|
|
||||||
|
updatePolicyBox();
|
||||||
|
updateSliderLimits();
|
||||||
|
updateSliderValues();
|
||||||
|
updateTimingMech();
|
||||||
|
|
||||||
|
connect( emuSchedPolicyBox , SIGNAL(activated(int)) , this, SLOT(emuSchedPolicyChange(int)) );
|
||||||
|
connect( emuSchedNiceSlider , SIGNAL(valueChanged(int)), this, SLOT(emuSchedNiceChange(int)) );
|
||||||
|
connect( emuSchedPrioSlider , SIGNAL(valueChanged(int)), this, SLOT(emuSchedPrioChange(int)) );
|
||||||
|
connect( guiSchedPolicyBox , SIGNAL(activated(int)) , this, SLOT(guiSchedPolicyChange(int)) );
|
||||||
|
connect( guiSchedNiceSlider , SIGNAL(valueChanged(int)), this, SLOT(guiSchedNiceChange(int)) );
|
||||||
|
connect( guiSchedPrioSlider , SIGNAL(valueChanged(int)), this, SLOT(guiSchedPrioChange(int)) );
|
||||||
|
connect( emuPrioCtlEna , SIGNAL(stateChanged(int)), this, SLOT(emuSchedCtlChange(int)) );
|
||||||
|
connect( timingDevSelBox , SIGNAL(activated(int)) , this, SLOT(emuTimingMechChange(int)) );
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
TimingConfDialog_t::~TimingConfDialog_t(void)
|
||||||
|
{
|
||||||
|
printf("Destroy Timing Config Window\n");
|
||||||
|
saveValues();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::closeEvent(QCloseEvent *event)
|
||||||
|
{
|
||||||
|
printf("Timing Close Window Event\n");
|
||||||
|
done(0);
|
||||||
|
deleteLater();
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::closeWindow(void)
|
||||||
|
{
|
||||||
|
//printf("Close Window\n");
|
||||||
|
done(0);
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::emuSchedCtlChange( int state )
|
||||||
|
{
|
||||||
|
g_config->setOption( "SDL.SetSchedParam", (state != Qt::Unchecked) );
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::saveValues(void)
|
||||||
|
{
|
||||||
|
int policy, prio, nice;
|
||||||
|
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nice = consoleWindow->emulatorThread->getNicePriority();
|
||||||
|
|
||||||
|
consoleWindow->emulatorThread->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
g_config->setOption( "SDL.EmuSchedPolicy", policy );
|
||||||
|
g_config->setOption( "SDL.EmuSchedPrioRt", prio );
|
||||||
|
g_config->setOption( "SDL.EmuSchedNice" , nice );
|
||||||
|
|
||||||
|
//printf("EMU Sched: %i %i %i\n", policy, prio, nice );
|
||||||
|
|
||||||
|
nice = consoleWindow->getNicePriority();
|
||||||
|
|
||||||
|
consoleWindow->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
g_config->setOption( "SDL.GuiSchedPolicy", policy );
|
||||||
|
g_config->setOption( "SDL.GuiSchedPrioRt", prio );
|
||||||
|
g_config->setOption( "SDL.GuiSchedNice" , nice );
|
||||||
|
|
||||||
|
//printf("GUI Sched: %i %i %i\n", policy, prio, nice );
|
||||||
|
|
||||||
|
g_config->save();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::emuSchedNiceChange(int val)
|
||||||
|
{
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fceuWrapperLock();
|
||||||
|
if ( consoleWindow->emulatorThread->setNicePriority( -val ) )
|
||||||
|
{
|
||||||
|
char msg[1024];
|
||||||
|
|
||||||
|
sprintf( msg, "Error: system call setPriority Failed\nReason: %s\n", strerror(errno) );
|
||||||
|
#ifdef __linux__
|
||||||
|
strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n");
|
||||||
|
strcat( msg, " /etc/security/limits.conf \n\n");
|
||||||
|
strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n");
|
||||||
|
strcat( msg, "* - priority 99 \n");
|
||||||
|
strcat( msg, "* - rtprio 99 \n");
|
||||||
|
strcat( msg, "* - nice -20 \n");
|
||||||
|
#endif
|
||||||
|
printf("%s\n", msg );
|
||||||
|
consoleWindow->QueueErrorMsgWindow( msg );
|
||||||
|
updateSliderValues();
|
||||||
|
}
|
||||||
|
fceuWrapperUnLock();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::emuSchedPrioChange(int val)
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fceuWrapperLock();
|
||||||
|
consoleWindow->emulatorThread->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
if ( consoleWindow->emulatorThread->setSchedParam( policy, val ) )
|
||||||
|
{
|
||||||
|
char msg[1024];
|
||||||
|
|
||||||
|
sprintf( msg, "Error: system call pthread_setschedparam Failed\nReason: %s\n", strerror(errno) );
|
||||||
|
#ifdef __linux__
|
||||||
|
strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n");
|
||||||
|
strcat( msg, " /etc/security/limits.conf \n\n");
|
||||||
|
strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n");
|
||||||
|
strcat( msg, "* - priority 99 \n");
|
||||||
|
strcat( msg, "* - rtprio 99 \n");
|
||||||
|
strcat( msg, "* - nice -20 \n");
|
||||||
|
#endif
|
||||||
|
printf("%s\n", msg );
|
||||||
|
consoleWindow->QueueErrorMsgWindow( msg );
|
||||||
|
updateSliderValues();
|
||||||
|
}
|
||||||
|
fceuWrapperUnLock();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::emuSchedPolicyChange( int index )
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fceuWrapperLock();
|
||||||
|
consoleWindow->emulatorThread->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
policy = emuSchedPolicyBox->itemData( index ).toInt();
|
||||||
|
|
||||||
|
if ( consoleWindow->emulatorThread->setSchedParam( policy, prio ) )
|
||||||
|
{
|
||||||
|
char msg[1024];
|
||||||
|
|
||||||
|
sprintf( msg, "Error: system call pthread_setschedparam Failed\nReason: %s\n", strerror(errno) );
|
||||||
|
#ifdef __linux__
|
||||||
|
strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n");
|
||||||
|
strcat( msg, " /etc/security/limits.conf \n\n");
|
||||||
|
strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n");
|
||||||
|
strcat( msg, "* - priority 99 \n");
|
||||||
|
strcat( msg, "* - rtprio 99 \n");
|
||||||
|
strcat( msg, "* - nice -20 \n");
|
||||||
|
#endif
|
||||||
|
printf("%s\n", msg );
|
||||||
|
consoleWindow->QueueErrorMsgWindow( msg );
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePolicyBox();
|
||||||
|
updateSliderLimits();
|
||||||
|
updateSliderValues();
|
||||||
|
fceuWrapperUnLock();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::guiSchedNiceChange(int val)
|
||||||
|
{
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fceuWrapperLock();
|
||||||
|
if ( consoleWindow->setNicePriority( -val ) )
|
||||||
|
{
|
||||||
|
char msg[1024];
|
||||||
|
|
||||||
|
sprintf( msg, "Error: system call setPriority Failed\nReason: %s\n", strerror(errno) );
|
||||||
|
#ifdef __linux__
|
||||||
|
strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n");
|
||||||
|
strcat( msg, " /etc/security/limits.conf \n\n");
|
||||||
|
strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n");
|
||||||
|
strcat( msg, "* - priority 99 \n");
|
||||||
|
strcat( msg, "* - rtprio 99 \n");
|
||||||
|
strcat( msg, "* - nice -20 \n");
|
||||||
|
#endif
|
||||||
|
printf("%s\n", msg );
|
||||||
|
consoleWindow->QueueErrorMsgWindow( msg );
|
||||||
|
updateSliderValues();
|
||||||
|
}
|
||||||
|
fceuWrapperUnLock();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::guiSchedPrioChange(int val)
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fceuWrapperLock();
|
||||||
|
consoleWindow->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
if ( consoleWindow->setSchedParam( policy, val ) )
|
||||||
|
{
|
||||||
|
char msg[1024];
|
||||||
|
|
||||||
|
sprintf( msg, "Error: system call pthread_setschedparam Failed\nReason: %s\n", strerror(errno) );
|
||||||
|
#ifdef __linux__
|
||||||
|
strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n");
|
||||||
|
strcat( msg, " /etc/security/limits.conf \n\n");
|
||||||
|
strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n");
|
||||||
|
strcat( msg, "* - priority 99 \n");
|
||||||
|
strcat( msg, "* - rtprio 99 \n");
|
||||||
|
strcat( msg, "* - nice -20 \n");
|
||||||
|
#endif
|
||||||
|
printf("%s\n", msg );
|
||||||
|
consoleWindow->QueueErrorMsgWindow( msg );
|
||||||
|
updateSliderValues();
|
||||||
|
}
|
||||||
|
fceuWrapperUnLock();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::guiSchedPolicyChange( int index )
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fceuWrapperLock();
|
||||||
|
consoleWindow->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
policy = guiSchedPolicyBox->itemData( index ).toInt();
|
||||||
|
|
||||||
|
if ( consoleWindow->setSchedParam( policy, prio ) )
|
||||||
|
{
|
||||||
|
char msg[1024];
|
||||||
|
|
||||||
|
sprintf( msg, "Error: system call pthread_setschedparam Failed\nReason: %s\n", strerror(errno) );
|
||||||
|
#ifdef __linux__
|
||||||
|
strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n");
|
||||||
|
strcat( msg, " /etc/security/limits.conf \n\n");
|
||||||
|
strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n");
|
||||||
|
strcat( msg, "* - priority 99 \n");
|
||||||
|
strcat( msg, "* - rtprio 99 \n");
|
||||||
|
strcat( msg, "* - nice -20 \n");
|
||||||
|
#endif
|
||||||
|
printf("%s\n", msg );
|
||||||
|
consoleWindow->QueueErrorMsgWindow( msg );
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePolicyBox();
|
||||||
|
updateSliderLimits();
|
||||||
|
updateSliderValues();
|
||||||
|
fceuWrapperUnLock();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::updatePolicyBox(void)
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
consoleWindow->emulatorThread->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
for (int j=0; j<emuSchedPolicyBox->count(); j++)
|
||||||
|
{
|
||||||
|
if ( emuSchedPolicyBox->itemData(j).toInt() == policy )
|
||||||
|
{
|
||||||
|
//printf("Found Policy %i %i\n", j , policy );
|
||||||
|
emuSchedPolicyBox->setCurrentIndex( j );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
consoleWindow->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
for (int j=0; j<guiSchedPolicyBox->count(); j++)
|
||||||
|
{
|
||||||
|
if ( guiSchedPolicyBox->itemData(j).toInt() == policy )
|
||||||
|
{
|
||||||
|
//printf("Found Policy %i %i\n", j , policy );
|
||||||
|
guiSchedPolicyBox->setCurrentIndex( j );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::updateSliderValues(void)
|
||||||
|
{
|
||||||
|
int policy, prio;
|
||||||
|
bool hasNicePerms;
|
||||||
|
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
consoleWindow->emulatorThread->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
emuSchedNiceSlider->setValue( -consoleWindow->emulatorThread->getNicePriority() );
|
||||||
|
emuSchedPrioSlider->setValue( prio );
|
||||||
|
|
||||||
|
if ( (policy == SCHED_RR) || (policy == SCHED_FIFO) )
|
||||||
|
{
|
||||||
|
emuSchedPrioLabel->setEnabled(true);
|
||||||
|
emuSchedPrioSlider->setEnabled(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emuSchedPrioLabel->setEnabled(false);
|
||||||
|
emuSchedPrioSlider->setEnabled(false);
|
||||||
|
}
|
||||||
|
hasNicePerms = hasNicePermissions( consoleWindow->emulatorThread->getNicePriority() );
|
||||||
|
|
||||||
|
emuSchedNiceLabel->setEnabled( hasNicePerms );
|
||||||
|
emuSchedNiceSlider->setEnabled( hasNicePerms );
|
||||||
|
|
||||||
|
consoleWindow->getSchedParam( policy, prio );
|
||||||
|
|
||||||
|
guiSchedNiceSlider->setValue( -consoleWindow->getNicePriority() );
|
||||||
|
guiSchedPrioSlider->setValue( prio );
|
||||||
|
|
||||||
|
if ( (policy == SCHED_RR) || (policy == SCHED_FIFO) )
|
||||||
|
{
|
||||||
|
guiSchedPrioLabel->setEnabled(true);
|
||||||
|
guiSchedPrioSlider->setEnabled(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
guiSchedPrioLabel->setEnabled(false);
|
||||||
|
guiSchedPrioSlider->setEnabled(false);
|
||||||
|
}
|
||||||
|
hasNicePerms = hasNicePermissions( consoleWindow->getNicePriority() );
|
||||||
|
|
||||||
|
guiSchedNiceLabel->setEnabled( hasNicePerms );
|
||||||
|
guiSchedNiceSlider->setEnabled( hasNicePerms );
|
||||||
|
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::updateSliderLimits(void)
|
||||||
|
{
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emuSchedNiceSlider->setMinimum( -20 );
|
||||||
|
emuSchedNiceSlider->setMaximum( 20 );
|
||||||
|
emuSchedPrioSlider->setMinimum( consoleWindow->emulatorThread->getMinSchedPriority() );
|
||||||
|
emuSchedPrioSlider->setMaximum( consoleWindow->emulatorThread->getMaxSchedPriority() );
|
||||||
|
|
||||||
|
guiSchedNiceSlider->setMinimum( -20 );
|
||||||
|
guiSchedNiceSlider->setMaximum( 20 );
|
||||||
|
guiSchedPrioSlider->setMinimum( consoleWindow->getMinSchedPriority() );
|
||||||
|
guiSchedPrioSlider->setMaximum( consoleWindow->getMaxSchedPriority() );
|
||||||
|
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::emuTimingMechChange( int index )
|
||||||
|
{
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
if ( consoleWindow == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fceuWrapperLock();
|
||||||
|
|
||||||
|
mode = timingDevSelBox->itemData( index ).toInt();
|
||||||
|
|
||||||
|
setTimingMode( mode );
|
||||||
|
|
||||||
|
RefreshThrottleFPS();
|
||||||
|
|
||||||
|
g_config->setOption("SDL.EmuTimingMech", mode);
|
||||||
|
|
||||||
|
fceuWrapperUnLock();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void TimingConfDialog_t::updateTimingMech(void)
|
||||||
|
{
|
||||||
|
int mode = getTimingMode();
|
||||||
|
|
||||||
|
for (int j=0; j<timingDevSelBox->count(); j++)
|
||||||
|
{
|
||||||
|
if ( timingDevSelBox->itemData(j).toInt() == mode )
|
||||||
|
{
|
||||||
|
timingDevSelBox->setCurrentIndex( j );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
|
@ -0,0 +1,65 @@
|
||||||
|
// TimingConf.h
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QSlider>
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QTreeView>
|
||||||
|
#include <QTreeWidget>
|
||||||
|
|
||||||
|
#include "Qt/main.h"
|
||||||
|
|
||||||
|
class TimingConfDialog_t : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TimingConfDialog_t(QWidget *parent = 0);
|
||||||
|
~TimingConfDialog_t(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void closeEvent(QCloseEvent *event);
|
||||||
|
|
||||||
|
QCheckBox *emuPrioCtlEna;
|
||||||
|
QComboBox *emuSchedPolicyBox;
|
||||||
|
QSlider *emuSchedPrioSlider;
|
||||||
|
QSlider *emuSchedNiceSlider;
|
||||||
|
QLabel *emuSchedPrioLabel;
|
||||||
|
QLabel *emuSchedNiceLabel;
|
||||||
|
QComboBox *guiSchedPolicyBox;
|
||||||
|
QSlider *guiSchedPrioSlider;
|
||||||
|
QSlider *guiSchedNiceSlider;
|
||||||
|
QLabel *guiSchedPrioLabel;
|
||||||
|
QLabel *guiSchedNiceLabel;
|
||||||
|
QComboBox *timingDevSelBox;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updatePolicyBox(void);
|
||||||
|
void updateSliderLimits(void);
|
||||||
|
void updateSliderValues(void);
|
||||||
|
void updateTimingMech(void);
|
||||||
|
void saveValues(void);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void closeWindow(void);
|
||||||
|
private slots:
|
||||||
|
void emuSchedCtlChange( int state );
|
||||||
|
void emuSchedNiceChange( int val );
|
||||||
|
void emuSchedPrioChange( int val );
|
||||||
|
void emuSchedPolicyChange( int index );
|
||||||
|
void guiSchedNiceChange( int val );
|
||||||
|
void guiSchedPrioChange( int val );
|
||||||
|
void guiSchedPolicyChange( int index );
|
||||||
|
void emuTimingMechChange( int index );
|
||||||
|
|
||||||
|
};
|
|
@ -315,6 +315,15 @@ InitConfig()
|
||||||
config->addOption("_useNativeFileDialog", "SDL.UseNativeFileDialog", false);
|
config->addOption("_useNativeFileDialog", "SDL.UseNativeFileDialog", false);
|
||||||
config->addOption("_useNativeMenuBar" , "SDL.UseNativeMenuBar", false);
|
config->addOption("_useNativeMenuBar" , "SDL.UseNativeMenuBar", false);
|
||||||
|
|
||||||
|
config->addOption("_setSchedParam" , "SDL.SetSchedParam" , 0);
|
||||||
|
config->addOption("_emuSchedPolicy" , "SDL.EmuSchedPolicy", 0);
|
||||||
|
config->addOption("_emuSchedNice" , "SDL.EmuSchedNice" , 0);
|
||||||
|
config->addOption("_emuSchedPrioRt" , "SDL.EmuSchedPrioRt", 40);
|
||||||
|
config->addOption("_guiSchedPolicy" , "SDL.GuiSchedPolicy", 0);
|
||||||
|
config->addOption("_guiSchedNice" , "SDL.GuiSchedNice" , 0);
|
||||||
|
config->addOption("_guiSchedPrioRt" , "SDL.GuiSchedPrioRt", 40);
|
||||||
|
config->addOption("_emuTimingMech" , "SDL.EmuTimingMech" , 0);
|
||||||
|
|
||||||
// fcm -> fm2 conversion
|
// fcm -> fm2 conversion
|
||||||
config->addOption("fcmconvert", "SDL.FCMConvert", "");
|
config->addOption("fcmconvert", "SDL.FCMConvert", "");
|
||||||
|
|
||||||
|
|
|
@ -737,6 +737,15 @@ int fceuWrapperInit( int argc, char *argv[] )
|
||||||
g_config->getOption("SDL.SubtitleDisplay", &id);
|
g_config->getOption("SDL.SubtitleDisplay", &id);
|
||||||
movieSubtitles = id ? true : false;
|
movieSubtitles = id ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emulation Timing Mechanism
|
||||||
|
{
|
||||||
|
int timingMode;
|
||||||
|
|
||||||
|
g_config->getOption("SDL.EmuTimingMech", &timingMode);
|
||||||
|
|
||||||
|
setTimingMode( timingMode );
|
||||||
|
}
|
||||||
|
|
||||||
// load the hotkeys from the config life
|
// load the hotkeys from the config life
|
||||||
setHotKeys();
|
setHotKeys();
|
||||||
|
@ -958,13 +967,6 @@ FCEUD_Update(uint8 *XBuf,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//if (!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused()))
|
|
||||||
//{
|
|
||||||
// while (SpeedThrottle())
|
|
||||||
// {
|
|
||||||
// FCEUD_UpdateInput();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
if (XBuf && (inited&4))
|
if (XBuf && (inited&4))
|
||||||
{
|
{
|
||||||
BlitScreen(XBuf); blitDone = 1;
|
BlitScreen(XBuf); blitDone = 1;
|
||||||
|
|
|
@ -4,16 +4,112 @@
|
||||||
#include "Qt/sdl.h"
|
#include "Qt/sdl.h"
|
||||||
#include "Qt/throttle.h"
|
#include "Qt/throttle.h"
|
||||||
|
|
||||||
|
#if defined(__linux) || defined(__APPLE__)
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static const double Slowest = 0.015625; // 1/64x speed (around 1 fps on NTSC)
|
static const double Slowest = 0.015625; // 1/64x speed (around 1 fps on NTSC)
|
||||||
static const double Fastest = 32; // 32x speed (around 1920 fps on NTSC)
|
static const double Fastest = 32; // 32x speed (around 1920 fps on NTSC)
|
||||||
static const double Normal = 1.0; // 1x speed (around 60 fps on NTSC)
|
static const double Normal = 1.0; // 1x speed (around 60 fps on NTSC)
|
||||||
|
|
||||||
static uint64 Lasttime, Nexttime;
|
static uint32 frameLateCounter = 0;
|
||||||
|
static double Lasttime=0, Nexttime=0, Latetime=0;
|
||||||
static double desired_frametime = (1.0 / 60.099823);
|
static double desired_frametime = (1.0 / 60.099823);
|
||||||
|
static double frameDeltaMin = 99999.0;
|
||||||
|
static double frameDeltaMax = 0.0;
|
||||||
|
static bool keepFrameTimeStats = false;
|
||||||
static int InFrame = 0;
|
static int InFrame = 0;
|
||||||
double g_fpsScale = Normal; // used by sdl.cpp
|
double g_fpsScale = Normal; // used by sdl.cpp
|
||||||
bool MaxSpeed = false;
|
bool MaxSpeed = false;
|
||||||
|
|
||||||
|
double getHighPrecTimeStamp(void)
|
||||||
|
{
|
||||||
|
#if defined(__linux) || defined(__APPLE__)
|
||||||
|
struct timespec ts;
|
||||||
|
double t;
|
||||||
|
|
||||||
|
clock_gettime( CLOCK_REALTIME, &ts );
|
||||||
|
|
||||||
|
t = (double)ts.tv_sec + (double)(ts.tv_nsec * 1.0e-9);
|
||||||
|
#else
|
||||||
|
double t;
|
||||||
|
|
||||||
|
t = (double)SDL_GetTicks();
|
||||||
|
|
||||||
|
t = t * 1e-3;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
static char useTimerFD = 0;
|
||||||
|
static int timerfd = -1;
|
||||||
|
|
||||||
|
static void setTimer( double hz )
|
||||||
|
{
|
||||||
|
struct itimerspec ispec;
|
||||||
|
|
||||||
|
if ( !useTimerFD )
|
||||||
|
{
|
||||||
|
if ( timerfd != -1 )
|
||||||
|
{
|
||||||
|
::close( timerfd ); timerfd = -1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( timerfd == -1 )
|
||||||
|
{
|
||||||
|
timerfd = timerfd_create( CLOCK_REALTIME, 0 );
|
||||||
|
|
||||||
|
if ( timerfd == -1 )
|
||||||
|
{
|
||||||
|
perror("timerfd_create failed: ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ispec.it_interval.tv_sec = 0;
|
||||||
|
ispec.it_interval.tv_nsec = (long)( 1.0e9 / hz );
|
||||||
|
ispec.it_value.tv_sec = ispec.it_interval.tv_sec;
|
||||||
|
ispec.it_value.tv_nsec = ispec.it_interval.tv_nsec;
|
||||||
|
|
||||||
|
if ( timerfd_settime( timerfd, 0, &ispec, NULL ) == -1 )
|
||||||
|
{
|
||||||
|
perror("timerfd_settime failed: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("Timer Set: %li ns\n", ispec.it_value.tv_nsec );
|
||||||
|
|
||||||
|
Lasttime = getHighPrecTimeStamp();
|
||||||
|
Nexttime = Lasttime + desired_frametime;
|
||||||
|
Latetime = Nexttime + desired_frametime;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int getTimingMode(void)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
if ( useTimerFD )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setTimingMode( int mode )
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
useTimerFD = (mode == 1);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* LOGMUL = exp(log(2) / 3)
|
/* LOGMUL = exp(log(2) / 3)
|
||||||
*
|
*
|
||||||
* This gives us a value such that if we do x*=LOGMUL three times,
|
* This gives us a value such that if we do x*=LOGMUL three times,
|
||||||
|
@ -28,7 +124,7 @@ bool MaxSpeed = false;
|
||||||
* Refreshes the FPS throttling variables.
|
* Refreshes the FPS throttling variables.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
RefreshThrottleFPS()
|
RefreshThrottleFPS(void)
|
||||||
{
|
{
|
||||||
double hz;
|
double hz;
|
||||||
int32_t fps = FCEUI_GetDesiredFPS(); // Do >> 24 to get in Hz
|
int32_t fps = FCEUI_GetDesiredFPS(); // Do >> 24 to get in Hz
|
||||||
|
@ -47,37 +143,67 @@ RefreshThrottleFPS()
|
||||||
Lasttime=0;
|
Lasttime=0;
|
||||||
Nexttime=0;
|
Nexttime=0;
|
||||||
InFrame=0;
|
InFrame=0;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
setTimer( hz * g_fpsScale );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int highPrecSleep( double timeSeconds )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#if defined(__linux) || defined(__APPLE__)
|
||||||
|
struct timespec req, rem;
|
||||||
|
|
||||||
|
req.tv_sec = (long)timeSeconds;
|
||||||
|
req.tv_nsec = (long)((timeSeconds - (double)req.tv_sec) * 1e9);
|
||||||
|
|
||||||
|
ret = nanosleep( &req, &rem );
|
||||||
|
#else
|
||||||
|
SDL_Delay( (long)(time_left * 1e3) );
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform FPS speed throttling by delaying until the next time slot.
|
* Perform FPS speed throttling by delaying until the next time slot.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
SpeedThrottle()
|
SpeedThrottle(void)
|
||||||
{
|
{
|
||||||
if (g_fpsScale >= 32)
|
if (g_fpsScale >= 32)
|
||||||
{
|
{
|
||||||
return 0; /* Done waiting */
|
return 0; /* Done waiting */
|
||||||
}
|
}
|
||||||
uint64 time_left;
|
double time_left;
|
||||||
uint64 cur_time;
|
double cur_time;
|
||||||
|
double frame_time = desired_frametime;
|
||||||
|
double quarterFrame = 0.250 * frame_time;
|
||||||
|
|
||||||
if (!Lasttime)
|
cur_time = getHighPrecTimeStamp();
|
||||||
|
|
||||||
|
if (Lasttime < 1.0)
|
||||||
{
|
{
|
||||||
Lasttime = SDL_GetTicks();
|
Lasttime = cur_time;
|
||||||
|
Latetime = Lasttime + frame_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InFrame)
|
if (!InFrame)
|
||||||
{
|
{
|
||||||
InFrame = 1;
|
InFrame = 1;
|
||||||
Nexttime = Lasttime + desired_frametime * 1000;
|
Nexttime = Lasttime + frame_time;
|
||||||
|
Latetime = Nexttime + frame_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_time = SDL_GetTicks();
|
if (cur_time >= Nexttime)
|
||||||
if(cur_time >= Nexttime)
|
{
|
||||||
time_left = 0;
|
time_left = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
time_left = Nexttime - cur_time;
|
time_left = Nexttime - cur_time;
|
||||||
|
}
|
||||||
|
|
||||||
if (time_left > 50)
|
if (time_left > 50)
|
||||||
{
|
{
|
||||||
|
@ -93,16 +219,81 @@ SpeedThrottle()
|
||||||
//fprintf(stderr, "attempting to sleep %Ld ms, frame complete=%s\n",
|
//fprintf(stderr, "attempting to sleep %Ld ms, frame complete=%s\n",
|
||||||
// time_left, InFrame?"no":"yes");
|
// time_left, InFrame?"no":"yes");
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if ( timerfd != -1 )
|
||||||
|
{
|
||||||
|
uint64_t val;
|
||||||
|
|
||||||
|
if ( read( timerfd, &val, sizeof(val) ) > 0 )
|
||||||
|
{
|
||||||
|
if ( val > 1 )
|
||||||
|
{
|
||||||
|
frameLateCounter += (val - 1);
|
||||||
|
//printf("Late Frame: %u \n", frameLateCounter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( time_left > 0 )
|
||||||
|
{
|
||||||
|
highPrecSleep( time_left );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( cur_time >= Latetime )
|
||||||
|
{
|
||||||
|
frameLateCounter++;
|
||||||
|
//printf("Late Frame: %u - %llu ms\n", frameLateCounter, cur_time - Latetime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ( time_left > 0 )
|
if ( time_left > 0 )
|
||||||
{
|
{
|
||||||
SDL_Delay(time_left);
|
highPrecSleep( time_left );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!InFrame)
|
|
||||||
{
|
{
|
||||||
Lasttime = SDL_GetTicks();
|
if ( cur_time >= Latetime )
|
||||||
|
{
|
||||||
|
frameLateCounter++;
|
||||||
|
//printf("Late Frame: %u - %llu ms\n", frameLateCounter, cur_time - Latetime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cur_time = getHighPrecTimeStamp();
|
||||||
|
|
||||||
|
if ( cur_time >= (Nexttime - quarterFrame) )
|
||||||
|
{
|
||||||
|
if ( keepFrameTimeStats )
|
||||||
|
{
|
||||||
|
double frameDelta;
|
||||||
|
|
||||||
|
frameDelta = (cur_time - Lasttime);
|
||||||
|
|
||||||
|
if ( frameDelta < frameDeltaMin )
|
||||||
|
{
|
||||||
|
frameDeltaMin = frameDelta;
|
||||||
|
}
|
||||||
|
if ( frameDelta > frameDeltaMax )
|
||||||
|
{
|
||||||
|
frameDeltaMax = frameDelta;
|
||||||
|
}
|
||||||
|
//printf("Frame Delta: %f us min:%f max:%f \n", frameDelta * 1e6, frameDeltaMin * 1e6, frameDeltaMax * 1e6 );
|
||||||
|
//printf("Frame Sleep Time: %f Target Error: %f us\n", time_left * 1e6, (cur_time - Nexttime) * 1e6 );
|
||||||
|
}
|
||||||
|
Lasttime = Nexttime;
|
||||||
|
Nexttime = Lasttime + frame_time;
|
||||||
|
Latetime = Nexttime + frame_time;
|
||||||
|
|
||||||
|
if ( cur_time >= Nexttime )
|
||||||
|
{
|
||||||
|
Lasttime = cur_time;
|
||||||
|
Nexttime = Lasttime + frame_time;
|
||||||
|
Latetime = Nexttime + frame_time;
|
||||||
|
}
|
||||||
return 0; /* Done waiting */
|
return 0; /* Done waiting */
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1; /* Must still wait some more */
|
return 1; /* Must still wait some more */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +304,7 @@ void IncreaseEmulationSpeed(void)
|
||||||
{
|
{
|
||||||
g_fpsScale *= LOGMUL;
|
g_fpsScale *= LOGMUL;
|
||||||
|
|
||||||
if(g_fpsScale > Fastest) g_fpsScale = Fastest;
|
if (g_fpsScale > Fastest) g_fpsScale = Fastest;
|
||||||
|
|
||||||
RefreshThrottleFPS();
|
RefreshThrottleFPS();
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
void RefreshThrottleFPS();
|
// throttle.h
|
||||||
int SpeedThrottle(void);
|
int SpeedThrottle(void);
|
||||||
|
void RefreshThrottleFPS(void);
|
||||||
|
int getTimingMode(void);
|
||||||
|
int setTimingMode(int mode);
|
||||||
|
|
Loading…
Reference in New Issue