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;
}
//----------------------------------------------------
void EmuScriptObject::frameAdvance()
{
script->frameAdvance();
}
//----------------------------------------------------
int EmuScriptObject::frameCount()
{
return FCEUMOV_GetFrame();
@ -156,6 +161,26 @@ bool EmuScriptObject::emulating()
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)
{
FCEU_DispMessage("%s",0, msg.toStdString().c_str());
@ -200,6 +225,85 @@ void EmuScriptObject::speedMode(const QString& mode)
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)
{
script->registerBeforeEmuFrame(func);
@ -854,6 +958,11 @@ void QtScriptInstance::loadUI(const QString& uiFilePath)
#endif
}
//----------------------------------------------------
void QtScriptInstance::frameAdvance()
{
frameAdvanceCount++;
}
//----------------------------------------------------
void QtScriptInstance::registerBeforeEmuFrame(const QJSValue& func)
{
if (onFrameBeginCallback != nullptr)
@ -1005,17 +1114,37 @@ void QtScriptInstance::stopRunning()
//----------------------------------------------------
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()
{
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()
{
static constexpr uint64_t funcTimeoutMs = 1000;
static constexpr unsigned int funcTimeoutMs = 1000;
if ( guiFuncState.isRunning() )
{
uint64_t timeRunningMs = guiFuncState.timeRunning();
unsigned int timeRunningMs = guiFuncState.timeCheck();
if (timeRunningMs > funcTimeoutMs)
{
@ -1059,7 +1188,7 @@ void QtScriptInstance::checkForHang()
if ( emuFuncState.isRunning() )
{
uint64_t timeRunningMs = emuFuncState.timeRunning();
unsigned int timeRunningMs = emuFuncState.timeCheck();
if (timeRunningMs > funcTimeoutMs)
{
@ -1236,7 +1365,7 @@ void ScriptMonitorThread_t::run()
script->checkForHang();
}
manager->scriptListMutex.unlock();
msleep(100);
msleep(ScriptExecutionState::checkPeriod);
}
//printf("Script Monitor Thread is Stopping...\n");
}

View File

@ -87,11 +87,15 @@ public slots:
Q_INVOKABLE void pause();
Q_INVOKABLE void unpause();
Q_INVOKABLE bool paused();
Q_INVOKABLE void frameAdvance();
Q_INVOKABLE int frameCount();
Q_INVOKABLE int lagCount();
Q_INVOKABLE bool lagged();
Q_INVOKABLE void setLagFlag(bool flag);
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 registerAfterFrame(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 bool loadRom(const QString& romPath);
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 QJSValue getScreenPixel(int x, int y, bool useBackup = false);
@ -169,29 +176,28 @@ class ScriptExecutionState
public:
void start()
{
startTime.readNew();
timeMs = 0;
executing = true;
}
void stop()
{
executing = false;
timeMs = 0;
}
bool isRunning(){ return executing; }
uint64_t timeRunning()
unsigned int timeCheck()
{
FCEU::timeStampRecord now, diff;
now.readNew();
diff = now - startTime;
return diff.toMilliSeconds();
unsigned int retval = timeMs;
timeMs += checkPeriod;
return retval;
}
static constexpr unsigned int checkPeriod = 100;
private:
bool executing = false;
FCEU::timeStampRecord startTime;
unsigned int timeMs = 0;
};
class QtScriptInstance : public QObject
@ -208,6 +214,7 @@ public:
void stopRunning();
int call(const QString& funcName, const QJSValueList& args = QJSValueList());
void frameAdvance();
void onFrameBegin();
void onFrameFinish();
void onGuiUpdate();
@ -238,6 +245,8 @@ private:
QJSValue *onGuiUpdateCallback = nullptr;
ScriptExecutionState guiFuncState;
ScriptExecutionState emuFuncState;
int frameAdvanceCount = 0;
int frameAdvanceState = 0;
bool running = false;
public slots: