mirror of https://github.com/mgba-emu/mgba.git
Core: Add symbol lookups from scripts
This commit is contained in:
parent
6a3002d398
commit
220b786c9c
|
@ -24,6 +24,7 @@ struct mScriptEngine {
|
||||||
bool (*isScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
|
bool (*isScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
|
||||||
bool (*loadScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
|
bool (*loadScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
|
||||||
void (*run)(struct mScriptEngine*);
|
void (*run)(struct mScriptEngine*);
|
||||||
|
bool (*lookupSymbol)(struct mScriptEngine*, const char* name, int32_t* out);
|
||||||
|
|
||||||
#ifdef USE_DEBUGGERS
|
#ifdef USE_DEBUGGERS
|
||||||
void (*debuggerEntered)(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
void (*debuggerEntered)(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||||
|
@ -44,6 +45,8 @@ void mScriptBridgeDebuggerEntered(struct mScriptBridge*, enum mDebuggerEntryReas
|
||||||
void mScriptBridgeRun(struct mScriptBridge*);
|
void mScriptBridgeRun(struct mScriptBridge*);
|
||||||
bool mScriptBridgeLoadScript(struct mScriptBridge*, const char* name);
|
bool mScriptBridgeLoadScript(struct mScriptBridge*, const char* name);
|
||||||
|
|
||||||
|
bool mScriptBridgeLookupSymbol(struct mScriptBridge*, const char* name, int32_t* out);
|
||||||
|
|
||||||
CXX_GUARD_END
|
CXX_GUARD_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,6 +19,12 @@ struct mScriptInfo {
|
||||||
bool success;
|
bool success;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mScriptSymbol {
|
||||||
|
const char* name;
|
||||||
|
int32_t* out;
|
||||||
|
bool success;
|
||||||
|
};
|
||||||
|
|
||||||
static void _seDeinit(void* value) {
|
static void _seDeinit(void* value) {
|
||||||
struct mScriptEngine* se = value;
|
struct mScriptEngine* se = value;
|
||||||
se->deinit(se);
|
se->deinit(se);
|
||||||
|
@ -33,6 +39,15 @@ static void _seTryLoad(const char* key, void* value, void* user) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _seLookupSymbol(const char* key, void* value, void* user) {
|
||||||
|
UNUSED(key);
|
||||||
|
struct mScriptEngine* se = value;
|
||||||
|
struct mScriptSymbol* si = user;
|
||||||
|
if (!si->success) {
|
||||||
|
si->success = se->lookupSymbol(se, si->name, si->out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void _seRun(const char* key, void* value, void* user) {
|
static void _seRun(const char* key, void* value, void* user) {
|
||||||
UNUSED(key);
|
UNUSED(key);
|
||||||
UNUSED(user);
|
UNUSED(user);
|
||||||
|
@ -111,3 +126,13 @@ bool mScriptBridgeLoadScript(struct mScriptBridge* sb, const char* name) {
|
||||||
vf->close(vf);
|
vf->close(vf);
|
||||||
return info.success;
|
return info.success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mScriptBridgeLookupSymbol(struct mScriptBridge* sb, const char* name, int32_t* out) {
|
||||||
|
struct mScriptSymbol info = {
|
||||||
|
.name = name,
|
||||||
|
.out = out,
|
||||||
|
.success = false
|
||||||
|
};
|
||||||
|
HashTableEnumerate(&sb->engines, _seLookupSymbol, &info);
|
||||||
|
return info.success;
|
||||||
|
}
|
||||||
|
|
|
@ -551,6 +551,11 @@ static void _lookupIdentifier(struct mDebugger* debugger, const char* name, stru
|
||||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||||
if (cliDebugger->system) {
|
if (cliDebugger->system) {
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
if (debugger->bridge && mScriptBridgeLookupSymbol(debugger->bridge, name, &dv->intValue)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, &dv->intValue, &dv->segmentValue)) {
|
if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, &dv->intValue, &dv->segmentValue)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,22 +72,26 @@ ffi.embedding_api('\n'.join(lines))
|
||||||
|
|
||||||
ffi.embedding_init_code("""
|
ffi.embedding_init_code("""
|
||||||
from mgba._pylib import ffi, lib
|
from mgba._pylib import ffi, lib
|
||||||
debugger = None
|
symbols = {}
|
||||||
|
globalSyms = {
|
||||||
|
'symbols': symbols
|
||||||
|
}
|
||||||
pendingCode = []
|
pendingCode = []
|
||||||
|
|
||||||
@ffi.def_extern()
|
@ffi.def_extern()
|
||||||
def mPythonSetDebugger(_debugger):
|
def mPythonSetDebugger(debugger):
|
||||||
from mgba.debugger import NativeDebugger, CLIDebugger
|
from mgba.debugger import NativeDebugger, CLIDebugger
|
||||||
global debugger
|
oldDebugger = globalSyms.get('debugger')
|
||||||
if debugger and debugger._native == _debugger:
|
if oldDebugger and oldDebugger._native == debugger:
|
||||||
return
|
return
|
||||||
if not _debugger:
|
if oldDebugger and not debugger:
|
||||||
debugger = None
|
del globalSyms['debugger']
|
||||||
return
|
return
|
||||||
if _debugger.type == lib.DEBUGGER_CLI:
|
if debugger.type == lib.DEBUGGER_CLI:
|
||||||
debugger = CLIDebugger(_debugger)
|
debugger = CLIDebugger(debugger)
|
||||||
else:
|
else:
|
||||||
debugger = NativeDebugger(_debugger)
|
debugger = NativeDebugger(debugger)
|
||||||
|
globalSyms['debugger'] = debugger
|
||||||
|
|
||||||
@ffi.def_extern()
|
@ffi.def_extern()
|
||||||
def mPythonLoadScript(name, vf):
|
def mPythonLoadScript(name, vf):
|
||||||
|
@ -106,18 +110,40 @@ ffi.embedding_init_code("""
|
||||||
def mPythonRunPending():
|
def mPythonRunPending():
|
||||||
global pendingCode
|
global pendingCode
|
||||||
for code in pendingCode:
|
for code in pendingCode:
|
||||||
exec(code)
|
exec(code, globalSyms, {})
|
||||||
pendingCode = []
|
pendingCode = []
|
||||||
|
|
||||||
@ffi.def_extern()
|
@ffi.def_extern()
|
||||||
def mPythonDebuggerEntered(reason, info):
|
def mPythonDebuggerEntered(reason, info):
|
||||||
global debugger
|
debugger = globalSyms['debugger']
|
||||||
if not debugger:
|
if not debugger:
|
||||||
return
|
return
|
||||||
if info == ffi.NULL:
|
if info == ffi.NULL:
|
||||||
info = None
|
info = None
|
||||||
for cb in debugger._cbs:
|
for cb in debugger._cbs:
|
||||||
cb(reason, info)
|
cb(reason, info)
|
||||||
|
|
||||||
|
@ffi.def_extern()
|
||||||
|
def mPythonLookupSymbol(name, outptr):
|
||||||
|
name = ffi.string(name).decode('utf-8')
|
||||||
|
if name not in symbols:
|
||||||
|
return False
|
||||||
|
sym = symbols[name]
|
||||||
|
val = None
|
||||||
|
try:
|
||||||
|
val = int(sym)
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
val = sym()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if val is None:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
outptr[0] = ffi.cast('int32_t', val)
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
""")
|
""")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -21,6 +21,7 @@ static void mPythonScriptEngineDeinit(struct mScriptEngine*);
|
||||||
static bool mPythonScriptEngineIsScript(struct mScriptEngine*, const char* name, struct VFile* vf);
|
static bool mPythonScriptEngineIsScript(struct mScriptEngine*, const char* name, struct VFile* vf);
|
||||||
static bool mPythonScriptEngineLoadScript(struct mScriptEngine*, const char* name, struct VFile* vf);
|
static bool mPythonScriptEngineLoadScript(struct mScriptEngine*, const char* name, struct VFile* vf);
|
||||||
static void mPythonScriptEngineRun(struct mScriptEngine*);
|
static void mPythonScriptEngineRun(struct mScriptEngine*);
|
||||||
|
static bool mPythonScriptEngineLookupSymbol(struct mScriptEngine*, const char* name, int32_t* out);
|
||||||
|
|
||||||
#ifdef USE_DEBUGGERS
|
#ifdef USE_DEBUGGERS
|
||||||
static void mPythonScriptDebuggerEntered(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
static void mPythonScriptDebuggerEntered(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||||
|
@ -39,6 +40,7 @@ struct mPythonScriptEngine* mPythonCreateScriptEngine(void) {
|
||||||
engine->d.isScript = mPythonScriptEngineIsScript;
|
engine->d.isScript = mPythonScriptEngineIsScript;
|
||||||
engine->d.loadScript = mPythonScriptEngineLoadScript;
|
engine->d.loadScript = mPythonScriptEngineLoadScript;
|
||||||
engine->d.run = mPythonScriptEngineRun;
|
engine->d.run = mPythonScriptEngineRun;
|
||||||
|
engine->d.lookupSymbol = mPythonScriptEngineLookupSymbol;
|
||||||
#ifdef USE_DEBUGGERS
|
#ifdef USE_DEBUGGERS
|
||||||
engine->d.debuggerEntered = mPythonScriptDebuggerEntered;
|
engine->d.debuggerEntered = mPythonScriptDebuggerEntered;
|
||||||
#endif
|
#endif
|
||||||
|
@ -89,6 +91,11 @@ void mPythonScriptEngineRun(struct mScriptEngine* se) {
|
||||||
mPythonRunPending();
|
mPythonRunPending();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mPythonScriptEngineLookupSymbol(struct mScriptEngine* se, const char* name, int32_t* out) {
|
||||||
|
struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se;
|
||||||
|
return mPythonLookupSymbol(name, out);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_DEBUGGERS
|
#ifdef USE_DEBUGGERS
|
||||||
void mPythonScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
|
void mPythonScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
|
||||||
struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se;
|
struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se;
|
||||||
|
|
|
@ -4,6 +4,7 @@ struct VFile;
|
||||||
|
|
||||||
extern bool mPythonLoadScript(const char*, struct VFile*);
|
extern bool mPythonLoadScript(const char*, struct VFile*);
|
||||||
extern void mPythonRunPending();
|
extern void mPythonRunPending();
|
||||||
|
extern bool mPythonLookupSymbol(const char* name, int32_t* out);
|
||||||
|
|
||||||
#ifdef USE_DEBUGGERS
|
#ifdef USE_DEBUGGERS
|
||||||
extern void mPythonSetDebugger(struct mDebugger*);
|
extern void mPythonSetDebugger(struct mDebugger*);
|
||||||
|
|
Loading…
Reference in New Issue