Added a QJSEngine wrapper class to maintain link to script instance and dialog window with new script objects.

This commit is contained in:
harry 2024-02-10 23:00:07 -05:00
parent 290c4ccd96
commit 2229d32720
2 changed files with 120 additions and 13 deletions

View File

@ -72,6 +72,8 @@
// File Base Name from Core
extern char FileBase[];
static thread_local FCEU::JSEngine* currentEngine = nullptr;
namespace JS
{
//----------------------------------------------------
@ -249,6 +251,8 @@ bool EmuStateScriptObject::loadFromFile(const QString& filepath)
FILE* inf = fopen(filepath.toLocal8Bit().data(),"rb");
if (inf == nullptr)
{
QString msg = "Warning: JS EmuState::loadFromFile failed to open file: " + filepath + "\n";
logMessage(FCEU::JSEngine::WARNING, msg);
return false;
}
fseek(inf,0,SEEK_END);
@ -257,7 +261,8 @@ bool EmuStateScriptObject::loadFromFile(const QString& filepath)
data = new EMUFILE_MEMORY(len);
if ( fread(data->buf(),1,len,inf) != static_cast<size_t>(len) )
{
FCEU_printf("Warning: JS EmuState::loadFromFile failed to load full buffer.\n");
QString msg = "Warning: JS EmuState::loadFromFile failed to load full buffer.\n";
logMessage(FCEU::JSEngine::WARNING, msg);
delete data;
data = nullptr;
}
@ -265,6 +270,16 @@ bool EmuStateScriptObject::loadFromFile(const QString& filepath)
return true;
}
//----------------------------------------------------
void EmuStateScriptObject::logMessage(int lvl, QString& msg)
{
auto* engine = FCEU::JSEngine::getCurrent();
if (engine != nullptr)
{
engine->logMessage(lvl, msg);
}
}
//----------------------------------------------------
//---- EMU Script Object
//----------------------------------------------------
EmuScriptObject::EmuScriptObject(QObject* parent)
@ -1125,6 +1140,48 @@ void MemoryScriptObject::unregisterAll()
}
} // JS
//----------------------------------------------------
//---- FCEU JSEngine
//----------------------------------------------------
namespace FCEU
{
JSEngine::JSEngine(QObject* parent)
: QJSEngine(parent)
{
}
JSEngine::~JSEngine()
{
}
void JSEngine::logMessage(int lvl, const QString& msg)
{
if (dialog != nullptr)
{
if (lvl <= _logLevel)
{
dialog->logOutput(msg);
}
}
}
void JSEngine::acquireThreadContext()
{
prevContext = currentEngine;
currentEngine = this;
}
void JSEngine::releaseThreadContext()
{
currentEngine = prevContext;
prevContext = nullptr;
}
JSEngine* JSEngine::getCurrent()
{
return currentEngine;
}
}
//----------------------------------------------------
//---- Qt Script Instance
//----------------------------------------------------
QtScriptInstance::QtScriptInstance(QObject* parent)
@ -1222,7 +1279,10 @@ void QtScriptInstance::resetEngine()
//----------------------------------------------------
int QtScriptInstance::initEngine()
{
engine = new QJSEngine(this);
engine = new FCEU::JSEngine(this);
engine->setScript(this);
engine->setDialog(dialog);
emu = new JS::EmuScriptObject(this);
rom = new JS::RomScriptObject(this);
@ -1289,7 +1349,9 @@ int QtScriptInstance::loadScriptFile( QString filepath )
scriptFile.close();
FCEU_WRAPPER_LOCK();
engine->acquireThreadContext();
QJSValue evalResult = engine->evaluate(fileText, filepath);
engine->releaseThreadContext();
FCEU_WRAPPER_UNLOCK();
if (evalResult.isError())
@ -1460,8 +1522,12 @@ int QtScriptInstance::runFunc(QJSValue &func, const QJSValueList& args)
state->start();
engine->acquireThreadContext();
QJSValue callResult = func.call(args);
engine->releaseThreadContext();
state->stop();
if (callResult.isError())

View File

@ -35,6 +35,46 @@
class QScriptDialog_t;
class QtScriptInstance;
namespace FCEU
{
class JSEngine : public QJSEngine
{
Q_OBJECT
public:
JSEngine(QObject* parent = nullptr);
~JSEngine();
QScriptDialog_t* getDialog(){ return dialog; }
QtScriptInstance* getScript(){ return script; }
void setDialog(QScriptDialog_t* _dialog){ dialog = _dialog; }
void setScript(QtScriptInstance* _script){ script = _script; }
enum logLevel
{
FATAL = 0,
CRITICAL,
WARNING,
INFO,
DEBUG,
};
void acquireThreadContext();
void releaseThreadContext();
void setLogLevel(enum logLevel lvl){ _logLevel = lvl; }
void logMessage(int lvl, const QString& msg);
static JSEngine* getCurrent();
private:
QScriptDialog_t* dialog = nullptr;
QtScriptInstance* script = nullptr;
int _logLevel = WARNING;
JSEngine* prevContext = nullptr;
};
} // FCEU
namespace JS
{
@ -87,6 +127,8 @@ private:
static int numInstances;
void logMessage(int lvl, QString& msg);
public slots:
Q_INVOKABLE bool save();
Q_INVOKABLE bool load();
@ -109,11 +151,11 @@ public:
EmuScriptObject(QObject* parent = nullptr);
~EmuScriptObject();
void setEngine(QJSEngine* _engine){ engine = _engine; }
void setEngine(FCEU::JSEngine* _engine){ engine = _engine; }
void setDialog(QScriptDialog_t* _dialog){ dialog = _dialog; }
private:
QJSEngine* engine = nullptr;
FCEU::JSEngine* engine = nullptr;
QScriptDialog_t* dialog = nullptr;
QtScriptInstance* script = nullptr;
@ -156,10 +198,10 @@ public:
RomScriptObject(QObject* parent = nullptr);
~RomScriptObject();
void setEngine(QJSEngine* _engine){ engine = _engine; }
void setEngine(FCEU::JSEngine* _engine){ engine = _engine; }
void setDialog(QScriptDialog_t* _dialog){ dialog = _dialog; }
private:
QJSEngine* engine = nullptr;
FCEU::JSEngine* engine = nullptr;
QScriptDialog_t* dialog = nullptr;
QtScriptInstance* script = nullptr;
@ -181,7 +223,7 @@ public:
MemoryScriptObject(QObject* parent = nullptr);
~MemoryScriptObject();
void setEngine(QJSEngine* _engine){ engine = _engine; }
void setEngine(FCEU::JSEngine* _engine){ engine = _engine; }
void setDialog(QScriptDialog_t* _dialog){ dialog = _dialog; }
void reset();
@ -191,7 +233,7 @@ public:
QJSValue* getExecFunc(int address) { return execFunc[address]; }
private:
static constexpr int AddressRange = 0x10000;
QJSEngine* engine = nullptr;
FCEU::JSEngine* engine = nullptr;
QScriptDialog_t* dialog = nullptr;
QtScriptInstance* script = nullptr;
QJSValue* readFunc[AddressRange] = { nullptr };
@ -240,10 +282,10 @@ public:
PpuScriptObject(QObject* parent = nullptr);
~PpuScriptObject();
void setEngine(QJSEngine* _engine){ engine = _engine; }
void setEngine(FCEU::JSEngine* _engine){ engine = _engine; }
void setDialog(QScriptDialog_t* _dialog){ dialog = _dialog; }
private:
QJSEngine* engine = nullptr;
FCEU::JSEngine* engine = nullptr;
QScriptDialog_t* dialog = nullptr;
QtScriptInstance* script = nullptr;
@ -309,8 +351,7 @@ public:
int throwError(QJSValue::ErrorType errorType, const QString &message = QString());
QObject* getObjectParent();
QJSEngine* getEngine(){ return engine; };
FCEU::JSEngine* getEngine(){ return engine; };
private:
int initEngine();
@ -320,7 +361,7 @@ private:
ScriptExecutionState* getExecutionState();
QJSEngine* engine = nullptr;
FCEU::JSEngine* engine = nullptr;
QScriptDialog_t* dialog = nullptr;
JS::EmuScriptObject* emu = nullptr;
JS::RomScriptObject* rom = nullptr;