Core: Add scripting debugger callbacks

This commit is contained in:
Vicki Pfau 2017-07-08 11:17:18 -07:00
parent d1ef27cff9
commit a033f8783b
9 changed files with 74 additions and 14 deletions

View File

@ -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);

View File

@ -30,7 +30,6 @@ enum mDebuggerState {
DEBUGGER_PAUSED,
DEBUGGER_RUNNING,
DEBUGGER_CUSTOM,
DEBUGGER_SCRIPT,
DEBUGGER_SHUTDOWN
};

View File

@ -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");
}

View File

@ -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) {

View File

@ -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)

View File

@ -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__":

View File

@ -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

View File

@ -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

View File

@ -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)