all repos — mgba @ 2d49a41a30bca9ad47457ad8825fc13b9e82de81

mGBA Game Boy Advance Emulator

src/core/scripting.c (view raw)

  1/* Copyright (c) 2013-2017 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba/core/scripting.h>
  7
  8#include <mgba-util/table.h>
  9#include <mgba-util/vfs.h>
 10
 11struct mScriptBridge {
 12	struct Table engines;
 13	struct mDebugger* debugger;
 14};
 15
 16struct mScriptInfo {
 17	const char* name;
 18	struct VFile* vf;
 19	bool success;
 20};
 21
 22static void _seDeinit(void* value) {
 23	struct mScriptEngine* se = value;
 24	se->deinit(se);
 25}
 26
 27static void _seTryLoad(const char* key, void* value, void* user) {
 28	UNUSED(key);
 29	struct mScriptEngine* se = value;
 30	struct mScriptInfo* si = user;
 31	if (!si->success && se->isScript(se, si->name, si->vf)) {
 32		si->success = se->loadScript(se, si->name, si->vf);
 33	}
 34}
 35
 36static void _seRun(const char* key, void* value, void* user) {
 37	UNUSED(key);
 38	UNUSED(user);
 39	struct mScriptEngine* se = value;
 40	se->run(se);
 41}
 42
 43#ifdef USE_DEBUGGERS
 44struct mScriptDebuggerEntry {
 45	enum mDebuggerEntryReason reason;
 46	struct mDebuggerEntryInfo* info;
 47};
 48
 49static void _seDebuggerEnter(const char* key, void* value, void* user) {
 50	UNUSED(key);
 51	struct mScriptEngine* se = value;
 52	struct mScriptDebuggerEntry* entry = user;
 53	se->debuggerEntered(se, entry->reason, entry->info);
 54}
 55#endif
 56
 57struct mScriptBridge* mScriptBridgeCreate(void) {
 58	struct mScriptBridge* sb = malloc(sizeof(*sb));
 59	HashTableInit(&sb->engines, 0, _seDeinit);
 60	sb->debugger = NULL;
 61	return sb;
 62}
 63
 64void mScriptBridgeDestroy(struct mScriptBridge* sb) {
 65	HashTableDeinit(&sb->engines);
 66	free(sb);
 67}
 68
 69void mScriptBridgeInstallEngine(struct mScriptBridge* sb, struct mScriptEngine* se) {
 70	if (!se->init(se, sb)) {
 71		return;
 72	}
 73	const char* name = se->name(se);
 74	HashTableInsert(&sb->engines, name, se);
 75}
 76
 77#ifdef USE_DEBUGGERS
 78void mScriptBridgeSetDebugger(struct mScriptBridge* sb, struct mDebugger* debugger) {
 79	sb->debugger = debugger;
 80	debugger->bridge = sb;
 81}
 82
 83struct mDebugger* mScriptBridgeGetDebugger(struct mScriptBridge* sb) {
 84	return sb->debugger;
 85}
 86
 87void mScriptBridgeDebuggerEntered(struct mScriptBridge* sb, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
 88	struct mScriptDebuggerEntry entry = {
 89		.reason = reason,
 90		.info = info
 91	};
 92	HashTableEnumerate(&sb->engines, _seDebuggerEnter, &entry);
 93}
 94#endif
 95
 96void mScriptBridgeRun(struct mScriptBridge* sb) {
 97	HashTableEnumerate(&sb->engines, _seRun, NULL);
 98}
 99
100bool mScriptBridgeLoadScript(struct mScriptBridge* sb, const char* name) {
101	struct VFile* vf = VFileOpen(name, O_RDONLY);
102	if (!vf) {
103		return false;
104	}
105	struct mScriptInfo info = {
106		.name = name,
107		.vf = vf,
108		.success = false
109	};
110	HashTableEnumerate(&sb->engines, _seTryLoad, &info);
111	vf->close(vf);
112	return info.success;
113}