From da612b51e8ebb61e9e7588dbe48b76a815595c4f Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 20 Dec 2014 01:43:48 -0800 Subject: [PATCH] Debugger: Add CLI "frame", frame advance command --- CHANGES | 1 + src/debugger/cli-debugger.c | 12 ++++++++++++ src/debugger/cli-debugger.h | 1 + src/debugger/debugger.c | 9 ++++++++- src/debugger/debugger.h | 2 ++ src/gba/gba-cli.c | 32 +++++++++++++++++++++++++++++++- src/gba/gba-cli.h | 3 +++ 7 files changed, 58 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index e92a6c495..4b80c29dd 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ Features: - Support for gamepad axes, e.g. analog sticks or triggers - Add scale presets for up to 6x + - Debugger: Add CLI "frame", frame advance command Bugfixes: - Qt: Fix issue with set frame sizes being the wrong height - Qt: Fix emulator crashing when full screen if a game is not running diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index 2c935e839..3a61cf076 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -684,10 +684,22 @@ static void _cliDebuggerDeinit(struct ARMDebugger* debugger) { } } +static void _cliDebuggerCustom(struct ARMDebugger* debugger) { + struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; + bool retain = false; + if (cliDebugger->system) { + retain = cliDebugger->system->custom(cliDebugger->system); + } + if (!retain && debugger->state == DEBUGGER_CUSTOM) { + debugger->state = DEBUGGER_RUNNING; + } +} + void CLIDebuggerCreate(struct CLIDebugger* debugger) { ARMDebuggerCreate(&debugger->d); debugger->d.init = _cliDebuggerInit; debugger->d.deinit = _cliDebuggerDeinit; + debugger->d.custom = _cliDebuggerCustom; debugger->d.paused = _commandLine; debugger->d.entered = _reportEntry; diff --git a/src/debugger/cli-debugger.h b/src/debugger/cli-debugger.h index 1590caa9d..873761215 100644 --- a/src/debugger/cli-debugger.h +++ b/src/debugger/cli-debugger.h @@ -43,6 +43,7 @@ struct CLIDebuggerSystem { void (*init)(struct CLIDebuggerSystem*); void (*deinit)(struct CLIDebuggerSystem*); + bool (*custom)(struct CLIDebuggerSystem*); uint32_t (*lookupIdentifier)(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index a9e5bcdc4..52a6a11e1 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -61,7 +61,7 @@ void ARMDebuggerRun(struct ARMDebugger* debugger) { while (debugger->state < DEBUGGER_EXITING) { if (!debugger->breakpoints) { while (debugger->state == DEBUGGER_RUNNING) { - ARMRun(debugger->cpu); + ARMRunLoop(debugger->cpu); } } else { while (debugger->state == DEBUGGER_RUNNING) { @@ -72,6 +72,13 @@ void ARMDebuggerRun(struct ARMDebugger* debugger) { switch (debugger->state) { case DEBUGGER_RUNNING: break; + case DEBUGGER_CUSTOM: + while (debugger->state == DEBUGGER_CUSTOM) { + ARMRun(debugger->cpu); + _checkBreakpoints(debugger); + debugger->custom(debugger); + } + break; case DEBUGGER_PAUSED: if (debugger->paused) { debugger->paused(debugger); diff --git a/src/debugger/debugger.h b/src/debugger/debugger.h index 0c6ef3b2e..95663a75f 100644 --- a/src/debugger/debugger.h +++ b/src/debugger/debugger.h @@ -15,6 +15,7 @@ extern const uint32_t ARM_DEBUGGER_ID; enum DebuggerState { DEBUGGER_PAUSED, DEBUGGER_RUNNING, + DEBUGGER_CUSTOM, DEBUGGER_EXITING, DEBUGGER_SHUTDOWN }; @@ -52,6 +53,7 @@ struct ARMDebugger { void (*deinit)(struct ARMDebugger*); void (*paused)(struct ARMDebugger*); void (*entered)(struct ARMDebugger*, enum DebuggerEntryReason); + void (*custom)(struct ARMDebugger*); __attribute__((format (printf, 3, 4))) void (*log)(struct ARMDebugger*, enum DebuggerLogLevel, const char* format, ...); diff --git a/src/gba/gba-cli.c b/src/gba/gba-cli.c index 55f1a9816..9684df002 100644 --- a/src/gba/gba-cli.c +++ b/src/gba/gba-cli.c @@ -15,12 +15,15 @@ static const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*); static void _GBACLIDebuggerDeinit(struct CLIDebuggerSystem*); +static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem*); static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); +static void _frame(struct CLIDebugger*, struct CLIDebugVector*); static void _load(struct CLIDebugger*, struct CLIDebugVector*); static void _save(struct CLIDebugger*, struct CLIDebugVector*); struct CLIDebuggerCommandSummary _GBACLIDebuggerCommands[] = { + { "frame", _frame, 0, "Frame advance" }, { "load", _load, CLIDVParse, "Load a savestate" }, { "save", _save, CLIDVParse, "Save a savestate" }, { 0, 0, 0, 0 } @@ -32,6 +35,7 @@ struct GBACLIDebugger* GBACLIDebuggerCreate(struct GBAThread* context) { #ifdef USE_CLI_DEBUGGER debugger->d.init = _GBACLIDebuggerInit; debugger->d.deinit = _GBACLIDebuggerDeinit; + debugger->d.custom = _GBACLIDebuggerCustom; debugger->d.lookupIdentifier = _GBACLIDebuggerLookupIdentifier; debugger->d.name = "Game Boy Advance"; @@ -45,13 +49,30 @@ struct GBACLIDebugger* GBACLIDebuggerCreate(struct GBAThread* context) { #ifdef USE_CLI_DEBUGGER static void _GBACLIDebuggerInit(struct CLIDebuggerSystem* debugger) { - UNUSED(debugger); + struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger; + + gbaDebugger->frameAdvance = false; } static void _GBACLIDebuggerDeinit(struct CLIDebuggerSystem* debugger) { UNUSED(debugger); } +static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem* debugger) { + struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger; + + if (gbaDebugger->frameAdvance) { + if (!gbaDebugger->inVblank && GBARegisterDISPSTATIsInVblank(gbaDebugger->context->gba->video.dispstat)) { + ARMDebuggerEnter(&gbaDebugger->d.p->d, DEBUGGER_ENTER_BREAKPOINT); + gbaDebugger->frameAdvance = false; + return false; + } + gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(gbaDebugger->context->gba->video.dispstat); + return true; + } + return false; +} + static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) { struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger; int i; @@ -65,6 +86,15 @@ static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem* debugg return 0; } +static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + UNUSED(dv); + debugger->d.state = DEBUGGER_CUSTOM; + + struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system; + gbaDebugger->frameAdvance = true; + gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(gbaDebugger->context->gba->video.dispstat); +} + static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { printf("%s\n", ERROR_MISSING_ARGS); diff --git a/src/gba/gba-cli.h b/src/gba/gba-cli.h index 9364019db..a1003352a 100644 --- a/src/gba/gba-cli.h +++ b/src/gba/gba-cli.h @@ -15,6 +15,9 @@ struct GBACLIDebugger { struct CLIDebuggerSystem d; struct GBAThread* context; + + bool frameAdvance; + bool inVblank; #endif };