Enable RT loop.

This commit is contained in:
Christian Speckner 2023-09-21 23:42:29 +02:00
parent f03435f1a9
commit 7b6ba75b7a
5 changed files with 105 additions and 6 deletions

View File

@ -598,6 +598,9 @@ class OSystem
// Indicates whether to stop the main loop
bool myQuitLoop{false};
static constexpr uInt32 FPS_METER_QUEUE_SIZE = 100;
FpsMeter myFpsMeter{FPS_METER_QUEUE_SIZE};
private:
FSNode myBaseDir, myStateDir, mySnapshotSaveDir, mySnapshotLoadDir,
myNVRamDir, myCfgDir, myHomeDir, myUserDir, myBezelDir;
@ -607,9 +610,6 @@ class OSystem
string myFeatures;
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
// base directory (where all settings are stored)
// Derived classes are free to ignore it and use their own defaults

View File

@ -5,6 +5,13 @@
#include <sys/sysinfo.h>
#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 {
void configureScheduler() {
@ -34,3 +41,73 @@ bool OSystemRTStella::initialize(const Settings::Options& 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();
}
}

View File

@ -23,6 +23,8 @@
class OSystemRTStella: public OSystemStandalone {
public:
bool initialize(const Settings::Options& options) override;
void mainLoop() override;
};
#endif // OSYSTEM_RTSTELLA_HXX

View File

@ -15,12 +15,15 @@
#define TRACE_MSG(m) m " in " STRINGIFY(__FILE__) ":" STRINGIFY(__LINE__)
namespace {
constexpr uint64_t TIMESLICE_NANOSECONDS = 100000;
constexpr uint64_t MAX_LAG_NANOSECONDS = 10 * TIMESLICE_NANOSECONDS;
constexpr uint64_t TIMESLICE_NANOSECONDS = 1000000;
constexpr uint64_t MAX_LAG_NANOSECONDS = 100000000;
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() {
@ -119,6 +122,8 @@ void RTEmulationWorker::suspend()
// the thread may transition to State::exception instead, so make sure that we rethrow
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
while (myState != State::running) rethrowPendingException();
__sync_synchronize();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -207,6 +214,7 @@ void RTEmulationWorker::stop()
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RTEmulationWorker::threadMain()
{
configureScheduler();
@ -260,6 +268,8 @@ void RTEmulationWorker::dispatchEmulation()
clock_gettime(CLOCK_MONOTONIC, &timeOffset);
myDispatchResult->setOk(0);
myState = State::running;
myPendingSignal = Signal::none;

View File

@ -64,6 +64,16 @@ class RTEmulationWorker {
void stop();
State state()
{
return myState;
}
bool isRunning()
{
return myState == State::running || myState == State::paused;
}
private:
void threadMain();