mirror of https://github.com/mgba-emu/mgba.git
Scripting: Start hooking things together
This commit is contained in:
parent
cdfa6ac54b
commit
7bb051b01d
|
@ -11,6 +11,10 @@
|
|||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/core/log.h>
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
#include <mgba/core/scripting.h>
|
||||
#include <mgba/script/context.h>
|
||||
#endif
|
||||
|
||||
struct mCoreThread;
|
||||
struct mCore;
|
||||
|
@ -39,6 +43,10 @@ struct mCoreThread {
|
|||
void* userData;
|
||||
void (*run)(struct mCoreThread*);
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
struct mScriptContext* scriptContext;
|
||||
#endif
|
||||
|
||||
struct mCoreThreadInternal* impl;
|
||||
};
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ struct mScriptEngineContext {
|
|||
struct mScriptContext* context;
|
||||
void (*destroy)(struct mScriptEngineContext*);
|
||||
|
||||
bool (*isScript)(struct mScriptEngineContext*, const char* name, struct VFile* vf);
|
||||
|
||||
bool (*setGlobal)(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
||||
struct mScriptValue* (*getGlobal)(struct mScriptEngineContext*, const char* name);
|
||||
|
||||
|
@ -48,10 +50,15 @@ void mScriptContextInit(struct mScriptContext*);
|
|||
void mScriptContextDeinit(struct mScriptContext*);
|
||||
|
||||
struct mScriptEngineContext* mScriptContextRegisterEngine(struct mScriptContext*, struct mScriptEngine2*);
|
||||
void mScriptContextRegisterEngines(struct mScriptContext*);
|
||||
|
||||
void mScriptContextSetGlobal(struct mScriptContext*, const char* key, struct mScriptValue* value);
|
||||
void mScriptContextRemoveGlobal(struct mScriptContext*, const char* key);
|
||||
|
||||
struct VFile;
|
||||
bool mScriptContextLoadVF(struct mScriptContext*, const char* name, struct VFile* vf);
|
||||
bool mScriptContextLoadFile(struct mScriptContext*, const char* path);
|
||||
|
||||
bool mScriptInvoke(const struct mScriptValue* fn, struct mScriptFrame* frame);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
|
|
@ -219,6 +219,12 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
mLogFilterLoad(threadContext->logger.d.filter, &core->config);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (threadContext->scriptContext) {
|
||||
mScriptContextAttachCore(threadContext->scriptContext, core);
|
||||
}
|
||||
#endif
|
||||
|
||||
mCoreThreadRewindParamsChanged(threadContext);
|
||||
if (threadContext->startCallback) {
|
||||
threadContext->startCallback(threadContext);
|
||||
|
@ -337,6 +343,11 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
if (threadContext->cleanCallback) {
|
||||
threadContext->cleanCallback(threadContext);
|
||||
}
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (threadContext->scriptContext) {
|
||||
mScriptContextDetachCore(threadContext->scriptContext);
|
||||
}
|
||||
#endif
|
||||
core->clearCoreCallbacks(core);
|
||||
|
||||
if (threadContext->logger.d.filter == &filter) {
|
||||
|
|
|
@ -4,12 +4,21 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/script/context.h>
|
||||
#ifdef USE_LUA
|
||||
#include <mgba/internal/script/lua.h>
|
||||
#endif
|
||||
|
||||
struct mScriptKVPair {
|
||||
const char* key;
|
||||
struct mScriptValue* value;
|
||||
};
|
||||
|
||||
struct mScriptFileInfo {
|
||||
const char* name;
|
||||
struct VFile* vf;
|
||||
struct mScriptEngineContext* context;
|
||||
};
|
||||
|
||||
static void _engineContextDestroy(void* ctx) {
|
||||
struct mScriptEngineContext* context = ctx;
|
||||
context->destroy(context);
|
||||
|
@ -28,6 +37,18 @@ static void _contextRemoveGlobal(const char* key, void* value, void* user) {
|
|||
context->setGlobal(context, user, NULL);
|
||||
}
|
||||
|
||||
static void _contextFindForFile(const char* key, void* value, void* user) {
|
||||
UNUSED(key);
|
||||
struct mScriptFileInfo* info = user;
|
||||
struct mScriptEngineContext* context = value;
|
||||
if (info->context) {
|
||||
return;
|
||||
}
|
||||
if (context->isScript(context, info->name, info->vf)) {
|
||||
info->context = context;
|
||||
}
|
||||
}
|
||||
|
||||
void mScriptContextInit(struct mScriptContext* context) {
|
||||
HashTableInit(&context->rootScope, 0, (void (*)(void*)) mScriptValueDeref);
|
||||
HashTableInit(&context->engines, 0, _engineContextDestroy);
|
||||
|
@ -46,6 +67,13 @@ struct mScriptEngineContext* mScriptContextRegisterEngine(struct mScriptContext*
|
|||
return ectx;
|
||||
}
|
||||
|
||||
void mScriptContextRegisterEngines(struct mScriptContext* context) {
|
||||
UNUSED(context);
|
||||
#ifdef USE_LUA
|
||||
mScriptContextRegisterEngine(context, mSCRIPT_ENGINE_LUA);
|
||||
#endif
|
||||
}
|
||||
|
||||
void mScriptContextSetGlobal(struct mScriptContext* context, const char* key, struct mScriptValue* value) {
|
||||
mScriptValueRef(value);
|
||||
HashTableInsert(&context->rootScope, key, value);
|
||||
|
@ -65,6 +93,29 @@ void mScriptContextRemoveGlobal(struct mScriptContext* context, const char* key)
|
|||
HashTableRemove(&context->rootScope, key);
|
||||
}
|
||||
|
||||
bool mScriptContextLoadVF(struct mScriptContext* context, const char* name, struct VFile* vf) {
|
||||
struct mScriptFileInfo info = {
|
||||
.name = name,
|
||||
.vf = vf,
|
||||
.context = NULL
|
||||
};
|
||||
HashTableEnumerate(&context->engines, _contextFindForFile, &info);
|
||||
if (!info.context) {
|
||||
return false;
|
||||
}
|
||||
return info.context->load(info.context, vf, NULL);
|
||||
}
|
||||
|
||||
bool mScriptContextLoadFile(struct mScriptContext* context, const char* path) {
|
||||
struct VFile* vf = VFileOpen(path, O_RDONLY);
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
bool ret = mScriptContextLoadVF(context, path, vf);
|
||||
vf->close(vf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool mScriptInvoke(const struct mScriptValue* val, struct mScriptFrame* frame) {
|
||||
if (val->type->base != mSCRIPT_TYPE_FUNCTION) {
|
||||
return false;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
static struct mScriptEngineContext* _luaCreate(struct mScriptEngine2*, struct mScriptContext*);
|
||||
|
||||
static void _luaDestroy(struct mScriptEngineContext*);
|
||||
static bool _luaIsScript(struct mScriptEngineContext*, const char*, struct VFile*);
|
||||
static struct mScriptValue* _luaGetGlobal(struct mScriptEngineContext*, const char* name);
|
||||
static bool _luaSetGlobal(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
||||
static bool _luaLoad(struct mScriptEngineContext*, struct VFile*, const char** error);
|
||||
|
@ -99,6 +100,7 @@ struct mScriptEngineContext* _luaCreate(struct mScriptEngine2* engine, struct mS
|
|||
luaContext->d = (struct mScriptEngineContext) {
|
||||
.context = context,
|
||||
.destroy = _luaDestroy,
|
||||
.isScript = _luaIsScript,
|
||||
.getGlobal = _luaGetGlobal,
|
||||
.setGlobal = _luaSetGlobal,
|
||||
.load = _luaLoad,
|
||||
|
@ -134,6 +136,15 @@ void _luaDestroy(struct mScriptEngineContext* ctx) {
|
|||
free(luaContext);
|
||||
}
|
||||
|
||||
bool _luaIsScript(struct mScriptEngineContext* ctx, const char* name, struct VFile* vf) {
|
||||
UNUSED(ctx);
|
||||
UNUSED(vf);
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
return endswith(name, ".lua");
|
||||
}
|
||||
|
||||
struct mScriptValue* _luaGetGlobal(struct mScriptEngineContext* ctx, const char* name) {
|
||||
struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx;
|
||||
lua_getglobal(luaContext->lua, name);
|
||||
|
|
Loading…
Reference in New Issue