Finished remaining JS interface functions for JS emu object.

This commit is contained in:
harry 2024-02-05 05:56:40 -05:00
parent 1fc813803e
commit 61da515f11
2 changed files with 156 additions and 18 deletions

View File

@ -131,6 +131,11 @@ bool EmuScriptObject::paused()
return FCEUI_EmulationPaused() != 0; return FCEUI_EmulationPaused() != 0;
} }
//---------------------------------------------------- //----------------------------------------------------
void EmuScriptObject::frameAdvance()
{
script->frameAdvance();
}
//----------------------------------------------------
int EmuScriptObject::frameCount() int EmuScriptObject::frameCount()
{ {
return FCEUMOV_GetFrame(); return FCEUMOV_GetFrame();
@ -156,6 +161,26 @@ bool EmuScriptObject::emulating()
return (GameInfo != nullptr); return (GameInfo != nullptr);
} }
//---------------------------------------------------- //----------------------------------------------------
bool EmuScriptObject::isReadOnly()
{
return FCEUI_GetMovieToggleReadOnly();
}
//----------------------------------------------------
void EmuScriptObject::setReadOnly(bool flag)
{
FCEUI_SetMovieToggleReadOnly(flag);
}
//----------------------------------------------------
void EmuScriptObject::setRenderPlanes(bool sprites, bool background)
{
FCEUI_SetRenderPlanes(sprites, background);
}
//----------------------------------------------------
void EmuScriptObject::exit()
{
fceuWrapperRequestAppExit();
}
//----------------------------------------------------
void EmuScriptObject::message(const QString& msg) void EmuScriptObject::message(const QString& msg)
{ {
FCEU_DispMessage("%s",0, msg.toStdString().c_str()); FCEU_DispMessage("%s",0, msg.toStdString().c_str());
@ -200,6 +225,85 @@ void EmuScriptObject::speedMode(const QString& mode)
FCEUD_SetEmulationSpeed(speed); FCEUD_SetEmulationSpeed(speed);
} }
//---------------------------------------------------- //----------------------------------------------------
bool EmuScriptObject::addGameGenie(const QString& code)
{
// Add a Game Genie code if it hasn't already been added
int GGaddr, GGcomp, GGval;
int i=0;
uint32 Caddr;
uint8 Cval;
int Ccompare, Ctype;
if (!FCEUI_DecodeGG(code.toLocal8Bit().data(), &GGaddr, &GGval, &GGcomp))
{
print("Failed to decode game genie code");
return false;
}
while (FCEUI_GetCheat(i,NULL,&Caddr,&Cval,&Ccompare,NULL,&Ctype))
{
if ((static_cast<uint32>(GGaddr) == Caddr) && (GGval == static_cast<int>(Cval)) && (GGcomp == Ccompare) && (Ctype == 1))
{
// Already Added, so consider it a success
return true;
}
i = i + 1;
}
if (FCEUI_AddCheat(code.toLocal8Bit().data(),GGaddr,GGval,GGcomp,1))
{
// Code was added
// Can't manage the display update the way I want, so I won't bother with it
// UpdateCheatsAdded();
return true;
}
else
{
// Code didn't get added
}
return false;
}
//----------------------------------------------------
bool EmuScriptObject::delGameGenie(const QString& code)
{
// Remove a Game Genie code. Very restrictive about deleted code.
int GGaddr, GGcomp, GGval;
uint32 i=0;
std::string Cname;
uint32 Caddr;
uint8 Cval;
int Ccompare, Ctype;
if (!FCEUI_DecodeGG(code.toLocal8Bit().data(), &GGaddr, &GGval, &GGcomp))
{
print("Failed to decode game genie code");
return false;
}
while (FCEUI_GetCheat(i,&Cname,&Caddr,&Cval,&Ccompare,NULL,&Ctype))
{
QString name = QString::fromStdString(Cname);
if ((code == name) && (static_cast<uint32>(GGaddr) == Caddr) && (GGval == static_cast<int>(Cval)) && (GGcomp == Ccompare) && (Ctype == 1))
{
// Delete cheat code
if (FCEUI_DelCheat(i))
{
return true;
}
else
{
return false;
}
}
i = i + 1;
}
// Cheat didn't exist, so it's not an error
return true;
}
//----------------------------------------------------
void EmuScriptObject::registerBeforeFrame(const QJSValue& func) void EmuScriptObject::registerBeforeFrame(const QJSValue& func)
{ {
script->registerBeforeEmuFrame(func); script->registerBeforeEmuFrame(func);
@ -854,6 +958,11 @@ void QtScriptInstance::loadUI(const QString& uiFilePath)
#endif #endif
} }
//---------------------------------------------------- //----------------------------------------------------
void QtScriptInstance::frameAdvance()
{
frameAdvanceCount++;
}
//----------------------------------------------------
void QtScriptInstance::registerBeforeEmuFrame(const QJSValue& func) void QtScriptInstance::registerBeforeEmuFrame(const QJSValue& func)
{ {
if (onFrameBeginCallback != nullptr) if (onFrameBeginCallback != nullptr)
@ -1005,17 +1114,37 @@ void QtScriptInstance::stopRunning()
//---------------------------------------------------- //----------------------------------------------------
void QtScriptInstance::onFrameBegin() void QtScriptInstance::onFrameBegin()
{ {
if (running && onFrameBeginCallback != nullptr && onFrameBeginCallback->isCallable()) if (running)
{ {
runFunc( *onFrameBeginCallback ); if (onFrameBeginCallback != nullptr && onFrameBeginCallback->isCallable())
{
runFunc( *onFrameBeginCallback );
}
if (frameAdvanceCount > 0)
{
if (frameAdvanceState == 0)
{
FCEUI_FrameAdvance();
frameAdvanceState = 1;
frameAdvanceCount--;
}
}
} }
} }
//---------------------------------------------------- //----------------------------------------------------
void QtScriptInstance::onFrameFinish() void QtScriptInstance::onFrameFinish()
{ {
if (running && onFrameFinishCallback != nullptr && onFrameFinishCallback->isCallable()) if (running)
{ {
runFunc( *onFrameFinishCallback ); if (onFrameFinishCallback != nullptr && onFrameFinishCallback->isCallable())
{
runFunc( *onFrameFinishCallback );
}
if (frameAdvanceState == 1)
{
FCEUI_FrameAdvanceEnd();
frameAdvanceState = 0;
}
} }
} }
//---------------------------------------------------- //----------------------------------------------------
@ -1044,11 +1173,11 @@ ScriptExecutionState* QtScriptInstance::getExecutionState()
//---------------------------------------------------- //----------------------------------------------------
void QtScriptInstance::checkForHang() void QtScriptInstance::checkForHang()
{ {
static constexpr uint64_t funcTimeoutMs = 1000; static constexpr unsigned int funcTimeoutMs = 1000;
if ( guiFuncState.isRunning() ) if ( guiFuncState.isRunning() )
{ {
uint64_t timeRunningMs = guiFuncState.timeRunning(); unsigned int timeRunningMs = guiFuncState.timeCheck();
if (timeRunningMs > funcTimeoutMs) if (timeRunningMs > funcTimeoutMs)
{ {
@ -1059,7 +1188,7 @@ void QtScriptInstance::checkForHang()
if ( emuFuncState.isRunning() ) if ( emuFuncState.isRunning() )
{ {
uint64_t timeRunningMs = emuFuncState.timeRunning(); unsigned int timeRunningMs = emuFuncState.timeCheck();
if (timeRunningMs > funcTimeoutMs) if (timeRunningMs > funcTimeoutMs)
{ {
@ -1236,7 +1365,7 @@ void ScriptMonitorThread_t::run()
script->checkForHang(); script->checkForHang();
} }
manager->scriptListMutex.unlock(); manager->scriptListMutex.unlock();
msleep(100); msleep(ScriptExecutionState::checkPeriod);
} }
//printf("Script Monitor Thread is Stopping...\n"); //printf("Script Monitor Thread is Stopping...\n");
} }

View File

@ -87,11 +87,15 @@ public slots:
Q_INVOKABLE void pause(); Q_INVOKABLE void pause();
Q_INVOKABLE void unpause(); Q_INVOKABLE void unpause();
Q_INVOKABLE bool paused(); Q_INVOKABLE bool paused();
Q_INVOKABLE void frameAdvance();
Q_INVOKABLE int frameCount(); Q_INVOKABLE int frameCount();
Q_INVOKABLE int lagCount(); Q_INVOKABLE int lagCount();
Q_INVOKABLE bool lagged(); Q_INVOKABLE bool lagged();
Q_INVOKABLE void setLagFlag(bool flag); Q_INVOKABLE void setLagFlag(bool flag);
Q_INVOKABLE bool emulating(); Q_INVOKABLE bool emulating();
Q_INVOKABLE bool isReadOnly();
Q_INVOKABLE void setReadOnly(bool flag);
Q_INVOKABLE void setRenderPlanes(bool sprites, bool background);
Q_INVOKABLE void registerBeforeFrame(const QJSValue& func); Q_INVOKABLE void registerBeforeFrame(const QJSValue& func);
Q_INVOKABLE void registerAfterFrame(const QJSValue& func); Q_INVOKABLE void registerAfterFrame(const QJSValue& func);
Q_INVOKABLE void registerStop(const QJSValue& func); Q_INVOKABLE void registerStop(const QJSValue& func);
@ -99,6 +103,9 @@ public slots:
Q_INVOKABLE void speedMode(const QString& mode); Q_INVOKABLE void speedMode(const QString& mode);
Q_INVOKABLE bool loadRom(const QString& romPath); Q_INVOKABLE bool loadRom(const QString& romPath);
Q_INVOKABLE bool onEmulationThread(); Q_INVOKABLE bool onEmulationThread();
Q_INVOKABLE bool addGameGenie(const QString& code);
Q_INVOKABLE bool delGameGenie(const QString& code);
Q_INVOKABLE void exit();
Q_INVOKABLE QString getDir(); Q_INVOKABLE QString getDir();
Q_INVOKABLE QJSValue getScreenPixel(int x, int y, bool useBackup = false); Q_INVOKABLE QJSValue getScreenPixel(int x, int y, bool useBackup = false);
@ -169,29 +176,28 @@ class ScriptExecutionState
public: public:
void start() void start()
{ {
startTime.readNew(); timeMs = 0;
executing = true; executing = true;
} }
void stop() void stop()
{ {
executing = false; executing = false;
timeMs = 0;
} }
bool isRunning(){ return executing; } bool isRunning(){ return executing; }
uint64_t timeRunning() unsigned int timeCheck()
{ {
FCEU::timeStampRecord now, diff; unsigned int retval = timeMs;
timeMs += checkPeriod;
now.readNew(); return retval;
diff = now - startTime;
return diff.toMilliSeconds();
} }
static constexpr unsigned int checkPeriod = 100;
private: private:
bool executing = false; bool executing = false;
FCEU::timeStampRecord startTime; unsigned int timeMs = 0;
}; };
class QtScriptInstance : public QObject class QtScriptInstance : public QObject
@ -208,6 +214,7 @@ public:
void stopRunning(); void stopRunning();
int call(const QString& funcName, const QJSValueList& args = QJSValueList()); int call(const QString& funcName, const QJSValueList& args = QJSValueList());
void frameAdvance();
void onFrameBegin(); void onFrameBegin();
void onFrameFinish(); void onFrameFinish();
void onGuiUpdate(); void onGuiUpdate();
@ -238,6 +245,8 @@ private:
QJSValue *onGuiUpdateCallback = nullptr; QJSValue *onGuiUpdateCallback = nullptr;
ScriptExecutionState guiFuncState; ScriptExecutionState guiFuncState;
ScriptExecutionState emuFuncState; ScriptExecutionState emuFuncState;
int frameAdvanceCount = 0;
int frameAdvanceState = 0;
bool running = false; bool running = false;
public slots: public slots: