mirror of https://github.com/stella-emu/stella.git
Enable RT loop.
This commit is contained in:
parent
f03435f1a9
commit
7b6ba75b7a
|
@ -598,6 +598,9 @@ class OSystem
|
||||||
// Indicates whether to stop the main loop
|
// Indicates whether to stop the main loop
|
||||||
bool myQuitLoop{false};
|
bool myQuitLoop{false};
|
||||||
|
|
||||||
|
static constexpr uInt32 FPS_METER_QUEUE_SIZE = 100;
|
||||||
|
FpsMeter myFpsMeter{FPS_METER_QUEUE_SIZE};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FSNode myBaseDir, myStateDir, mySnapshotSaveDir, mySnapshotLoadDir,
|
FSNode myBaseDir, myStateDir, mySnapshotSaveDir, mySnapshotLoadDir,
|
||||||
myNVRamDir, myCfgDir, myHomeDir, myUserDir, myBezelDir;
|
myNVRamDir, myCfgDir, myHomeDir, myUserDir, myBezelDir;
|
||||||
|
@ -607,9 +610,6 @@ class OSystem
|
||||||
string myFeatures;
|
string myFeatures;
|
||||||
string myBuildInfo;
|
string myBuildInfo;
|
||||||
|
|
||||||
static constexpr uInt32 FPS_METER_QUEUE_SIZE = 100;
|
|
||||||
FpsMeter myFpsMeter{FPS_METER_QUEUE_SIZE};
|
|
||||||
|
|
||||||
// If not empty, a hint for derived classes to use this as the
|
// If not empty, a hint for derived classes to use this as the
|
||||||
// base directory (where all settings are stored)
|
// base directory (where all settings are stored)
|
||||||
// Derived classes are free to ignore it and use their own defaults
|
// Derived classes are free to ignore it and use their own defaults
|
||||||
|
|
|
@ -5,6 +5,13 @@
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
|
|
||||||
#include "Logger.hxx"
|
#include "Logger.hxx"
|
||||||
|
#include "RTEmulationWorker.hxx"
|
||||||
|
#include "EventHandler.hxx"
|
||||||
|
#include "TimerManager.hxx"
|
||||||
|
#include "DispatchResult.hxx"
|
||||||
|
#include "Console.hxx"
|
||||||
|
#include "Debugger.hxx"
|
||||||
|
#include "TIA.hxx"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void configureScheduler() {
|
void configureScheduler() {
|
||||||
|
@ -34,3 +41,73 @@ bool OSystemRTStella::initialize(const Settings::Options& options)
|
||||||
|
|
||||||
return OSystemStandalone::initialize(options);
|
return OSystemStandalone::initialize(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OSystemRTStella::mainLoop()
|
||||||
|
{
|
||||||
|
RTEmulationWorker worker;
|
||||||
|
DispatchResult dispatchResult;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
TIA& tia = myConsole->tia();
|
||||||
|
|
||||||
|
if (worker.isRunning()) worker.suspend();
|
||||||
|
|
||||||
|
const EventHandlerState oldState = myEventHandler->state();
|
||||||
|
const bool workerWasRunning = worker.isRunning();
|
||||||
|
|
||||||
|
if (oldState == EventHandlerState::EMULATION && worker.isRunning()) {
|
||||||
|
tia.renderToFrameBuffer();
|
||||||
|
|
||||||
|
switch (dispatchResult.getStatus()) {
|
||||||
|
case DispatchResult::Status::ok:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DispatchResult::Status::debugger:
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
myDebugger->start(
|
||||||
|
dispatchResult.getMessage(),
|
||||||
|
dispatchResult.getAddress(),
|
||||||
|
dispatchResult.wasReadTrap(),
|
||||||
|
dispatchResult.getToolTip()
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DispatchResult::Status::fatal:
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
myDebugger->startWithFatalError(dispatchResult.getMessage());
|
||||||
|
#else
|
||||||
|
cerr << dispatchResult.getMessage() << endl;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
cout << (int)dispatchResult.getStatus() << endl << std::flush;
|
||||||
|
throw runtime_error("invalid emulation dispatch result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myEventHandler->poll(TimerManager::getTicks());
|
||||||
|
if (myQuitLoop) break;
|
||||||
|
|
||||||
|
if (dispatchResult.getStatus() == DispatchResult::Status::ok && myEventHandler->frying() && worker.isRunning())
|
||||||
|
myConsole->fry();
|
||||||
|
|
||||||
|
const EventHandlerState newState = myEventHandler->state();
|
||||||
|
|
||||||
|
if (newState == EventHandlerState::EMULATION && !worker.isRunning()) {
|
||||||
|
worker.start(myConsole->emulationTiming().cyclesPerSecond(), &dispatchResult, &tia);
|
||||||
|
myFpsMeter.reset();
|
||||||
|
} else if (newState != EventHandlerState::EMULATION && worker.isRunning()) {
|
||||||
|
worker.stop();
|
||||||
|
} else if (newState == EventHandlerState::EMULATION && worker.isRunning()) {
|
||||||
|
worker.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldState == EventHandlerState::EMULATION && workerWasRunning)
|
||||||
|
myFrameBuffer->updateInEmulationMode(myFpsMeter.fps());
|
||||||
|
else
|
||||||
|
myFrameBuffer->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
class OSystemRTStella: public OSystemStandalone {
|
class OSystemRTStella: public OSystemStandalone {
|
||||||
public:
|
public:
|
||||||
bool initialize(const Settings::Options& options) override;
|
bool initialize(const Settings::Options& options) override;
|
||||||
|
|
||||||
|
void mainLoop() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // OSYSTEM_RTSTELLA_HXX
|
#endif // OSYSTEM_RTSTELLA_HXX
|
||||||
|
|
|
@ -15,12 +15,15 @@
|
||||||
#define TRACE_MSG(m) m " in " STRINGIFY(__FILE__) ":" STRINGIFY(__LINE__)
|
#define TRACE_MSG(m) m " in " STRINGIFY(__FILE__) ":" STRINGIFY(__LINE__)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr uint64_t TIMESLICE_NANOSECONDS = 100000;
|
constexpr uint64_t TIMESLICE_NANOSECONDS = 1000000;
|
||||||
constexpr uint64_t MAX_LAG_NANOSECONDS = 10 * TIMESLICE_NANOSECONDS;
|
constexpr uint64_t MAX_LAG_NANOSECONDS = 100000000;
|
||||||
|
|
||||||
inline Int64 timeDifferenceNanoseconds(const struct timespec& from, const struct timespec& to)
|
inline Int64 timeDifferenceNanoseconds(const struct timespec& from, const struct timespec& to)
|
||||||
{
|
{
|
||||||
return (from.tv_sec - to.tv_sec) * 1000000000 + (from.tv_nsec - to.tv_nsec);
|
uInt64 deltaSec = from.tv_sec - to.tv_sec;
|
||||||
|
uInt64 deltaNsec = from.tv_nsec - to.tv_nsec;
|
||||||
|
|
||||||
|
return deltaSec * 1000000000 + deltaNsec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void configureScheduler() {
|
void configureScheduler() {
|
||||||
|
@ -119,6 +122,8 @@ void RTEmulationWorker::suspend()
|
||||||
|
|
||||||
// the thread may transition to State::exception instead, so make sure that we rethrow
|
// the thread may transition to State::exception instead, so make sure that we rethrow
|
||||||
while (myState != State::paused) rethrowPendingException();
|
while (myState != State::paused) rethrowPendingException();
|
||||||
|
|
||||||
|
__sync_synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -133,6 +138,8 @@ void RTEmulationWorker::resume()
|
||||||
|
|
||||||
// the thread may transition to State::exception instead, so make sure that we rethrow
|
// the thread may transition to State::exception instead, so make sure that we rethrow
|
||||||
while (myState != State::running) rethrowPendingException();
|
while (myState != State::running) rethrowPendingException();
|
||||||
|
|
||||||
|
__sync_synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -207,6 +214,7 @@ void RTEmulationWorker::stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void RTEmulationWorker::threadMain()
|
void RTEmulationWorker::threadMain()
|
||||||
{
|
{
|
||||||
configureScheduler();
|
configureScheduler();
|
||||||
|
@ -260,6 +268,8 @@ void RTEmulationWorker::dispatchEmulation()
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &timeOffset);
|
clock_gettime(CLOCK_MONOTONIC, &timeOffset);
|
||||||
|
|
||||||
|
myDispatchResult->setOk(0);
|
||||||
|
|
||||||
myState = State::running;
|
myState = State::running;
|
||||||
myPendingSignal = Signal::none;
|
myPendingSignal = Signal::none;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,16 @@ class RTEmulationWorker {
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
State state()
|
||||||
|
{
|
||||||
|
return myState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isRunning()
|
||||||
|
{
|
||||||
|
return myState == State::running || myState == State::paused;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void threadMain();
|
void threadMain();
|
||||||
|
|
Loading…
Reference in New Issue