mirror of https://github.com/mgba-emu/mgba.git
Core: Add scripting debugger callbacks
This commit is contained in:
parent
d1ef27cff9
commit
a033f8783b
|
@ -10,9 +10,12 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#include <mgba/debugger/debugger.h>
|
||||
#endif
|
||||
|
||||
struct mScriptBridge;
|
||||
struct VFile;
|
||||
struct mDebugger;
|
||||
struct mScriptEngine {
|
||||
const char* (*name)(struct mScriptEngine*);
|
||||
|
||||
|
@ -21,6 +24,10 @@ struct mScriptEngine {
|
|||
bool (*isScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
|
||||
bool (*loadScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
|
||||
void (*run)(struct mScriptEngine*);
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
void (*debuggerEntered)(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct mScriptBridge* mScriptBridgeCreate(void);
|
||||
|
@ -28,8 +35,11 @@ void mScriptBridgeDestroy(struct mScriptBridge*);
|
|||
|
||||
void mScriptBridgeInstallEngine(struct mScriptBridge*, struct mScriptEngine*);
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
void mScriptBridgeSetDebugger(struct mScriptBridge*, struct mDebugger*);
|
||||
struct mDebugger* mScriptBridgeGetDebugger(struct mScriptBridge*);
|
||||
void mScriptBridgeDebuggerEntered(struct mScriptBridge*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||
#endif
|
||||
|
||||
void mScriptBridgeRun(struct mScriptBridge*);
|
||||
bool mScriptBridgeLoadScript(struct mScriptBridge*, const char* name);
|
||||
|
|
|
@ -30,7 +30,6 @@ enum mDebuggerState {
|
|||
DEBUGGER_PAUSED,
|
||||
DEBUGGER_RUNNING,
|
||||
DEBUGGER_CUSTOM,
|
||||
DEBUGGER_SCRIPT,
|
||||
DEBUGGER_SHUTDOWN
|
||||
};
|
||||
|
||||
|
|
|
@ -428,7 +428,7 @@ static void _source(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
|||
return;
|
||||
}
|
||||
if (debugger->d.bridge && mScriptBridgeLoadScript(debugger->d.bridge, dv->charValue)) {
|
||||
debugger->d.state = DEBUGGER_SCRIPT;
|
||||
mScriptBridgeRun(debugger->d.bridge);
|
||||
} else {
|
||||
debugger->backend->printf(debugger->backend, "Failed to load script\n");
|
||||
}
|
||||
|
|
|
@ -97,14 +97,6 @@ void mDebuggerRun(struct mDebugger* debugger) {
|
|||
debugger->state = DEBUGGER_RUNNING;
|
||||
}
|
||||
break;
|
||||
case DEBUGGER_SCRIPT:
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
mScriptBridgeRun(debugger->bridge);
|
||||
#endif
|
||||
if (debugger->state == DEBUGGER_SCRIPT) {
|
||||
debugger->state = DEBUGGER_PAUSED;
|
||||
}
|
||||
break;
|
||||
case DEBUGGER_SHUTDOWN:
|
||||
return;
|
||||
}
|
||||
|
@ -122,6 +114,11 @@ void mDebuggerEnter(struct mDebugger* debugger, enum mDebuggerEntryReason reason
|
|||
if (debugger->platform->entered) {
|
||||
debugger->platform->entered(debugger->platform, reason, info);
|
||||
}
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (debugger->bridge) {
|
||||
mScriptBridgeDebuggerEntered(debugger->bridge, reason, info);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mDebuggerInit(void* cpu, struct mCPUComponent* component) {
|
||||
|
|
|
@ -32,6 +32,7 @@ file(GLOB PYTHON_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
|||
add_library(${BINARY_NAME}-pylib STATIC ${CMAKE_CURRENT_BINARY_DIR}/lib.c ${PYTHON_SRC})
|
||||
add_dependencies(${BINARY_NAME}-pylib ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py)
|
||||
set_target_properties(${BINARY_NAME}-pylib PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR};${INCLUDE_DIRECTORIES}")
|
||||
set_target_properties(${BINARY_NAME}-pylib PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
|
||||
set(PYTHON_LIBRARY ${BINARY_NAME}-pylib PARENT_SCOPE)
|
||||
|
||||
add_custom_target(${BINARY_NAME}-py ALL DEPENDS ${BINARY_NAME}-pylib ${CMAKE_CURRENT_BINARY_DIR}/build/lib/${BINARY_NAME}/__init__.py)
|
||||
|
|
|
@ -78,6 +78,8 @@ ffi.embedding_init_code("""
|
|||
def mPythonSetDebugger(_debugger):
|
||||
from mgba.debugger import NativeDebugger
|
||||
global debugger
|
||||
if debugger and debugger._native == _debugger:
|
||||
return
|
||||
debugger = _debugger and NativeDebugger(_debugger)
|
||||
|
||||
@ffi.def_extern()
|
||||
|
@ -99,6 +101,16 @@ ffi.embedding_init_code("""
|
|||
for code in pendingCode:
|
||||
exec(code)
|
||||
pendingCode = []
|
||||
|
||||
@ffi.def_extern()
|
||||
def mPythonDebuggerEntered(reason, info):
|
||||
global debugger
|
||||
if not debugger:
|
||||
return
|
||||
if info == ffi.NULL:
|
||||
info = None
|
||||
for cb in debugger._cbs:
|
||||
cb(reason, info)
|
||||
""")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
#include "engine.h"
|
||||
|
||||
#include <mgba/core/scripting.h>
|
||||
#include <mgba/debugger/debugger.h>
|
||||
#include <mgba-util/string.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#include <mgba/debugger/debugger.h>
|
||||
#endif
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
static const char* mPythonScriptEngineName(struct mScriptEngine*);
|
||||
|
@ -19,6 +22,10 @@ static bool mPythonScriptEngineIsScript(struct mScriptEngine*, const char* name,
|
|||
static bool mPythonScriptEngineLoadScript(struct mScriptEngine*, const char* name, struct VFile* vf);
|
||||
static void mPythonScriptEngineRun(struct mScriptEngine*);
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
static void mPythonScriptDebuggerEntered(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||
#endif
|
||||
|
||||
struct mPythonScriptEngine {
|
||||
struct mScriptEngine d;
|
||||
struct mScriptBridge* sb;
|
||||
|
@ -32,6 +39,9 @@ struct mPythonScriptEngine* mPythonCreateScriptEngine(void) {
|
|||
engine->d.isScript = mPythonScriptEngineIsScript;
|
||||
engine->d.loadScript = mPythonScriptEngineLoadScript;
|
||||
engine->d.run = mPythonScriptEngineRun;
|
||||
#ifdef USE_DEBUGGERS
|
||||
engine->d.debuggerEntered = mPythonScriptDebuggerEntered;
|
||||
#endif
|
||||
engine->sb = NULL;
|
||||
return engine;
|
||||
}
|
||||
|
@ -78,3 +88,16 @@ void mPythonScriptEngineRun(struct mScriptEngine* se) {
|
|||
|
||||
mPythonRunPending();
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
void mPythonScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
|
||||
struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se;
|
||||
|
||||
struct mDebugger* debugger = mScriptBridgeGetDebugger(engine->sb);
|
||||
if (!debugger) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPythonDebuggerEntered(reason, info);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
struct mDebugger;
|
||||
#include "flags.h"
|
||||
|
||||
struct VFile;
|
||||
|
||||
extern void mPythonSetDebugger(struct mDebugger*);
|
||||
extern bool mPythonLoadScript(const char*, struct VFile*);
|
||||
extern void mPythonRunPending();
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
extern void mPythonSetDebugger(struct mDebugger*);
|
||||
extern void mPythonDebuggerEntered(enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||
#endif
|
||||
|
|
|
@ -26,8 +26,18 @@ class NativeDebugger(IRunner):
|
|||
WATCHPOINT_READ = lib.WATCHPOINT_READ
|
||||
WATCHPOINT_RW = lib.WATCHPOINT_RW
|
||||
|
||||
BREAKPOINT_HARDWARE = lib.BREAKPOINT_HARDWARE
|
||||
BREAKPOINT_SOFTWARE = lib.BREAKPOINT_SOFTWARE
|
||||
|
||||
ENTER_MANUAL = lib.DEBUGGER_ENTER_MANUAL
|
||||
ENTER_ATTACHED = lib.DEBUGGER_ENTER_ATTACHED
|
||||
ENTER_BREAKPOINT = lib.DEBUGGER_ENTER_BREAKPOINT
|
||||
ENTER_WATCHPOINT = lib.DEBUGGER_ENTER_WATCHPOINT
|
||||
ENTER_ILLEGAL_OP = lib.DEBUGGER_ENTER_ILLEGAL_OP
|
||||
|
||||
def __init__(self, native):
|
||||
self._native = native
|
||||
self._cbs = []
|
||||
self._core = Core._detect(native.core)
|
||||
self._core._wasReset = True
|
||||
|
||||
|
@ -65,3 +75,6 @@ class NativeDebugger(IRunner):
|
|||
if not self._native.platform.clearWatchpoint:
|
||||
raise RuntimeError("Platform does not support watchpoints")
|
||||
self._native.platform.clearWatchpoint(self._native.platform, address)
|
||||
|
||||
def addCallback(self, cb):
|
||||
self._cbs.append(cb)
|
||||
|
|
Loading…
Reference in New Issue