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
|
CXX_GUARD_START
|
||||||
|
|
||||||
#include <mgba/core/log.h>
|
#include <mgba/core/log.h>
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
#include <mgba/core/scripting.h>
|
||||||
|
#include <mgba/script/context.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct mCoreThread;
|
struct mCoreThread;
|
||||||
struct mCore;
|
struct mCore;
|
||||||
|
@ -39,6 +43,10 @@ struct mCoreThread {
|
||||||
void* userData;
|
void* userData;
|
||||||
void (*run)(struct mCoreThread*);
|
void (*run)(struct mCoreThread*);
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
struct mScriptContext* scriptContext;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct mCoreThreadInternal* impl;
|
struct mCoreThreadInternal* impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,8 @@ struct mScriptEngineContext {
|
||||||
struct mScriptContext* context;
|
struct mScriptContext* context;
|
||||||
void (*destroy)(struct mScriptEngineContext*);
|
void (*destroy)(struct mScriptEngineContext*);
|
||||||
|
|
||||||
|
bool (*isScript)(struct mScriptEngineContext*, const char* name, struct VFile* vf);
|
||||||
|
|
||||||
bool (*setGlobal)(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
bool (*setGlobal)(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
||||||
struct mScriptValue* (*getGlobal)(struct mScriptEngineContext*, const char* name);
|
struct mScriptValue* (*getGlobal)(struct mScriptEngineContext*, const char* name);
|
||||||
|
|
||||||
|
@ -48,10 +50,15 @@ void mScriptContextInit(struct mScriptContext*);
|
||||||
void mScriptContextDeinit(struct mScriptContext*);
|
void mScriptContextDeinit(struct mScriptContext*);
|
||||||
|
|
||||||
struct mScriptEngineContext* mScriptContextRegisterEngine(struct mScriptContext*, struct mScriptEngine2*);
|
struct mScriptEngineContext* mScriptContextRegisterEngine(struct mScriptContext*, struct mScriptEngine2*);
|
||||||
|
void mScriptContextRegisterEngines(struct mScriptContext*);
|
||||||
|
|
||||||
void mScriptContextSetGlobal(struct mScriptContext*, const char* key, struct mScriptValue* value);
|
void mScriptContextSetGlobal(struct mScriptContext*, const char* key, struct mScriptValue* value);
|
||||||
void mScriptContextRemoveGlobal(struct mScriptContext*, const char* key);
|
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);
|
bool mScriptInvoke(const struct mScriptValue* fn, struct mScriptFrame* frame);
|
||||||
|
|
||||||
CXX_GUARD_END
|
CXX_GUARD_END
|
||||||
|
|
|
@ -219,6 +219,12 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
||||||
mLogFilterLoad(threadContext->logger.d.filter, &core->config);
|
mLogFilterLoad(threadContext->logger.d.filter, &core->config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
if (threadContext->scriptContext) {
|
||||||
|
mScriptContextAttachCore(threadContext->scriptContext, core);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
mCoreThreadRewindParamsChanged(threadContext);
|
mCoreThreadRewindParamsChanged(threadContext);
|
||||||
if (threadContext->startCallback) {
|
if (threadContext->startCallback) {
|
||||||
threadContext->startCallback(threadContext);
|
threadContext->startCallback(threadContext);
|
||||||
|
@ -337,6 +343,11 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
||||||
if (threadContext->cleanCallback) {
|
if (threadContext->cleanCallback) {
|
||||||
threadContext->cleanCallback(threadContext);
|
threadContext->cleanCallback(threadContext);
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
if (threadContext->scriptContext) {
|
||||||
|
mScriptContextDetachCore(threadContext->scriptContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
core->clearCoreCallbacks(core);
|
core->clearCoreCallbacks(core);
|
||||||
|
|
||||||
if (threadContext->logger.d.filter == &filter) {
|
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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include <mgba/script/context.h>
|
#include <mgba/script/context.h>
|
||||||
|
#ifdef USE_LUA
|
||||||
|
#include <mgba/internal/script/lua.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct mScriptKVPair {
|
struct mScriptKVPair {
|
||||||
const char* key;
|
const char* key;
|
||||||
struct mScriptValue* value;
|
struct mScriptValue* value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mScriptFileInfo {
|
||||||
|
const char* name;
|
||||||
|
struct VFile* vf;
|
||||||
|
struct mScriptEngineContext* context;
|
||||||
|
};
|
||||||
|
|
||||||
static void _engineContextDestroy(void* ctx) {
|
static void _engineContextDestroy(void* ctx) {
|
||||||
struct mScriptEngineContext* context = ctx;
|
struct mScriptEngineContext* context = ctx;
|
||||||
context->destroy(context);
|
context->destroy(context);
|
||||||
|
@ -28,6 +37,18 @@ static void _contextRemoveGlobal(const char* key, void* value, void* user) {
|
||||||
context->setGlobal(context, user, NULL);
|
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) {
|
void mScriptContextInit(struct mScriptContext* context) {
|
||||||
HashTableInit(&context->rootScope, 0, (void (*)(void*)) mScriptValueDeref);
|
HashTableInit(&context->rootScope, 0, (void (*)(void*)) mScriptValueDeref);
|
||||||
HashTableInit(&context->engines, 0, _engineContextDestroy);
|
HashTableInit(&context->engines, 0, _engineContextDestroy);
|
||||||
|
@ -46,6 +67,13 @@ struct mScriptEngineContext* mScriptContextRegisterEngine(struct mScriptContext*
|
||||||
return ectx;
|
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) {
|
void mScriptContextSetGlobal(struct mScriptContext* context, const char* key, struct mScriptValue* value) {
|
||||||
mScriptValueRef(value);
|
mScriptValueRef(value);
|
||||||
HashTableInsert(&context->rootScope, key, value);
|
HashTableInsert(&context->rootScope, key, value);
|
||||||
|
@ -65,6 +93,29 @@ void mScriptContextRemoveGlobal(struct mScriptContext* context, const char* key)
|
||||||
HashTableRemove(&context->rootScope, 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) {
|
bool mScriptInvoke(const struct mScriptValue* val, struct mScriptFrame* frame) {
|
||||||
if (val->type->base != mSCRIPT_TYPE_FUNCTION) {
|
if (val->type->base != mSCRIPT_TYPE_FUNCTION) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
static struct mScriptEngineContext* _luaCreate(struct mScriptEngine2*, struct mScriptContext*);
|
static struct mScriptEngineContext* _luaCreate(struct mScriptEngine2*, struct mScriptContext*);
|
||||||
|
|
||||||
static void _luaDestroy(struct mScriptEngineContext*);
|
static void _luaDestroy(struct mScriptEngineContext*);
|
||||||
|
static bool _luaIsScript(struct mScriptEngineContext*, const char*, struct VFile*);
|
||||||
static struct mScriptValue* _luaGetGlobal(struct mScriptEngineContext*, const char* name);
|
static struct mScriptValue* _luaGetGlobal(struct mScriptEngineContext*, const char* name);
|
||||||
static bool _luaSetGlobal(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
static bool _luaSetGlobal(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
||||||
static bool _luaLoad(struct mScriptEngineContext*, struct VFile*, const char** error);
|
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) {
|
luaContext->d = (struct mScriptEngineContext) {
|
||||||
.context = context,
|
.context = context,
|
||||||
.destroy = _luaDestroy,
|
.destroy = _luaDestroy,
|
||||||
|
.isScript = _luaIsScript,
|
||||||
.getGlobal = _luaGetGlobal,
|
.getGlobal = _luaGetGlobal,
|
||||||
.setGlobal = _luaSetGlobal,
|
.setGlobal = _luaSetGlobal,
|
||||||
.load = _luaLoad,
|
.load = _luaLoad,
|
||||||
|
@ -134,6 +136,15 @@ void _luaDestroy(struct mScriptEngineContext* ctx) {
|
||||||
free(luaContext);
|
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 mScriptValue* _luaGetGlobal(struct mScriptEngineContext* ctx, const char* name) {
|
||||||
struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx;
|
struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx;
|
||||||
lua_getglobal(luaContext->lua, name);
|
lua_getglobal(luaContext->lua, name);
|
||||||
|
|
Loading…
Reference in New Issue