diff --git a/src/drivers/Qt/QtScriptManager.cpp b/src/drivers/Qt/QtScriptManager.cpp index f2bb376c..9cdfdcfc 100644 --- a/src/drivers/Qt/QtScriptManager.cpp +++ b/src/drivers/Qt/QtScriptManager.cpp @@ -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(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()) diff --git a/src/drivers/Qt/QtScriptManager.h b/src/drivers/Qt/QtScriptManager.h index 0bed1b82..71bcda27 100644 --- a/src/drivers/Qt/QtScriptManager.h +++ b/src/drivers/Qt/QtScriptManager.h @@ -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;