mirror of https://github.com/mgba-emu/mgba.git
Debugger: Begin GB debugger
This commit is contained in:
parent
1cc0bdeec1
commit
b365628aad
|
@ -0,0 +1,31 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "cli.h"
|
||||
|
||||
#include "lr35902/cli-debugger.h"
|
||||
|
||||
#ifdef USE_CLI_DEBUGGER
|
||||
|
||||
struct CLIDebuggerCommandSummary _GBCLIDebuggerCommands[] = {
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore* core) {
|
||||
UNUSED(core);
|
||||
struct CLIDebuggerSystem* debugger = malloc(sizeof(struct CLIDebuggerSystem));
|
||||
LR35902CLIDebuggerCreate(debugger);
|
||||
debugger->init = NULL;
|
||||
debugger->deinit = NULL;
|
||||
debugger->custom = NULL;
|
||||
debugger->lookupIdentifier = NULL;
|
||||
|
||||
debugger->name = "Game Boy";
|
||||
debugger->commands = _GBCLIDebuggerCommands;
|
||||
|
||||
return debugger;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef GB_CLI_H
|
||||
#define GB_CLI_H
|
||||
|
||||
#ifdef USE_CLI_DEBUGGER
|
||||
#include "debugger/cli-debugger.h"
|
||||
|
||||
struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore*);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -6,8 +6,10 @@
|
|||
#include "core.h"
|
||||
|
||||
#include "core/core.h"
|
||||
#include "gb/cli.h"
|
||||
#include "gb/gb.h"
|
||||
#include "gb/renderers/software.h"
|
||||
#include "lr35902/debugger.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/patch.h"
|
||||
|
||||
|
@ -15,6 +17,8 @@ struct GBCore {
|
|||
struct mCore d;
|
||||
struct GBVideoSoftwareRenderer renderer;
|
||||
uint8_t keys;
|
||||
struct mCPUComponent* components[CPU_COMPONENT_MAX];
|
||||
struct mDebuggerPlatform* debuggerPlatform;
|
||||
};
|
||||
|
||||
static bool _GBCoreInit(struct mCore* core) {
|
||||
|
@ -29,9 +33,11 @@ static bool _GBCoreInit(struct mCore* core) {
|
|||
}
|
||||
core->cpu = cpu;
|
||||
core->board = gb;
|
||||
gbcore->debuggerPlatform = NULL;
|
||||
|
||||
GBCreate(gb);
|
||||
LR35902SetComponents(cpu, &gb->d, 0, 0);
|
||||
memset(gbcore->components, 0, sizeof(gbcore->components));
|
||||
LR35902SetComponents(cpu, &gb->d, CPU_COMPONENT_MAX, gbcore->components);
|
||||
LR35902Init(cpu);
|
||||
|
||||
GBVideoSoftwareRendererCreate(&gbcore->renderer);
|
||||
|
@ -290,11 +296,49 @@ static void _GBCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t val
|
|||
}
|
||||
|
||||
static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
|
||||
return false;
|
||||
UNUSED(core);
|
||||
switch (type) {
|
||||
#ifdef USE_CLI_DEBUGGER
|
||||
case DEBUGGER_CLI:
|
||||
return true;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct mDebuggerPlatform* _GBCoreDebuggerPlatform(struct mCore* core) {
|
||||
return 0;
|
||||
struct GBCore* gbcore = (struct GBCore*) core;
|
||||
if (!gbcore->debuggerPlatform) {
|
||||
gbcore->debuggerPlatform = LR35902DebuggerPlatformCreate();
|
||||
}
|
||||
return gbcore->debuggerPlatform;
|
||||
}
|
||||
|
||||
static struct CLIDebuggerSystem* _GBCoreCliDebuggerSystem(struct mCore* core) {
|
||||
#ifdef USE_CLI_DEBUGGER
|
||||
return GBCLIDebuggerCreate(core);
|
||||
#else
|
||||
UNUSED(core);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _GBCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
|
||||
struct LR35902Core* cpu = core->cpu;
|
||||
if (core->debugger) {
|
||||
LR35902HotplugDetach(cpu, CPU_COMPONENT_DEBUGGER);
|
||||
}
|
||||
cpu->components[CPU_COMPONENT_DEBUGGER] = &debugger->d;
|
||||
LR35902HotplugAttach(cpu, CPU_COMPONENT_DEBUGGER);
|
||||
core->debugger = debugger;
|
||||
}
|
||||
|
||||
static void _GBCoreDetachDebugger(struct mCore* core) {
|
||||
struct LR35902Core* cpu = core->cpu;
|
||||
LR35902HotplugDetach(cpu, CPU_COMPONENT_DEBUGGER);
|
||||
cpu->components[CPU_COMPONENT_DEBUGGER] = NULL;
|
||||
core->debugger = NULL;
|
||||
}
|
||||
|
||||
struct mCore* GBCoreCreate(void) {
|
||||
|
@ -347,5 +391,8 @@ struct mCore* GBCoreCreate(void) {
|
|||
core->busWrite32 = _GBCoreBusWrite32;
|
||||
core->supportsDebuggerType = _GBCoreSupportsDebuggerType;
|
||||
core->debuggerPlatform = _GBCoreDebuggerPlatform;
|
||||
core->cliDebuggerSystem = _GBCoreCliDebuggerSystem;
|
||||
core->attachDebugger = _GBCoreAttachDebugger;
|
||||
core->detachDebugger = _GBCoreDetachDebugger;
|
||||
return core;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ static bool _GBACoreInit(struct mCore* core) {
|
|||
gbacore->overrides = 0;
|
||||
|
||||
GBACreate(gba);
|
||||
// TODO: Restore debugger and cheats
|
||||
// TODO: Restore cheats
|
||||
memset(gbacore->components, 0, sizeof(gbacore->components));
|
||||
ARMSetComponents(cpu, &gba->d, CPU_COMPONENT_MAX, gbacore->components);
|
||||
ARMInit(cpu);
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#ifdef USE_CLI_DEBUGGER
|
||||
|
||||
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);
|
||||
|
||||
|
@ -33,7 +32,7 @@ struct GBACLIDebugger* GBACLIDebuggerCreate(struct mCore* core) {
|
|||
struct GBACLIDebugger* debugger = malloc(sizeof(struct GBACLIDebugger));
|
||||
ARMCLIDebuggerCreate(&debugger->d);
|
||||
debugger->d.init = _GBACLIDebuggerInit;
|
||||
debugger->d.deinit = _GBACLIDebuggerDeinit;
|
||||
debugger->d.deinit = NULL;
|
||||
debugger->d.custom = _GBACLIDebuggerCustom;
|
||||
debugger->d.lookupIdentifier = _GBACLIDebuggerLookupIdentifier;
|
||||
|
||||
|
@ -51,10 +50,6 @@ static void _GBACLIDebuggerInit(struct CLIDebuggerSystem* debugger) {
|
|||
gbaDebugger->frameAdvance = false;
|
||||
}
|
||||
|
||||
static void _GBACLIDebuggerDeinit(struct CLIDebuggerSystem* debugger) {
|
||||
UNUSED(debugger);
|
||||
}
|
||||
|
||||
static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem* debugger) {
|
||||
struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger;
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "cli-debugger.h"
|
||||
|
||||
#ifdef USE_CLI_DEBUGGER
|
||||
#include "core/core.h"
|
||||
#include "debugger/cli-debugger.h"
|
||||
#include "lr35902/lr35902.h"
|
||||
|
||||
static void _printStatus(struct CLIDebuggerSystem*);
|
||||
|
||||
static struct CLIDebuggerCommandSummary _lr35902Commands[] = {
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static inline void _printFlags(union FlagRegister f) {
|
||||
printf("[%c%c%c%c]\n",
|
||||
f.z ? 'Z' : '-',
|
||||
f.n ? 'N' : '-',
|
||||
f.h ? 'H' : '-',
|
||||
f.c ? 'C' : '-');
|
||||
}
|
||||
|
||||
static void _printStatus(struct CLIDebuggerSystem* debugger) {
|
||||
struct LR35902Core* cpu = debugger->p->d.core->cpu;
|
||||
printf("A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af);
|
||||
printf("B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc);
|
||||
printf("D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de);
|
||||
printf("H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl);
|
||||
printf("PC: %04X SP: %04X\n", cpu->pc, cpu->sp);
|
||||
_printFlags(cpu->f);
|
||||
}
|
||||
|
||||
static uint32_t _lookupIdentifier(struct mDebugger* debugger, const char* name, struct CLIDebugVector* dv) {
|
||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||
struct LR35902Core* cpu = debugger->core->cpu;
|
||||
if (strcmp(name, "a") == 0) {
|
||||
return cpu->a;
|
||||
}
|
||||
if (strcmp(name, "b") == 0) {
|
||||
return cpu->b;
|
||||
}
|
||||
if (strcmp(name, "c") == 0) {
|
||||
return cpu->c;
|
||||
}
|
||||
if (strcmp(name, "d") == 0) {
|
||||
return cpu->d;
|
||||
}
|
||||
if (strcmp(name, "e") == 0) {
|
||||
return cpu->e;
|
||||
}
|
||||
if (strcmp(name, "h") == 0) {
|
||||
return cpu->h;
|
||||
}
|
||||
if (strcmp(name, "l") == 0) {
|
||||
return cpu->l;
|
||||
}
|
||||
if (strcmp(name, "bc") == 0) {
|
||||
return cpu->bc;
|
||||
}
|
||||
if (strcmp(name, "de") == 0) {
|
||||
return cpu->de;
|
||||
}
|
||||
if (strcmp(name, "hl") == 0) {
|
||||
return cpu->hl;
|
||||
}
|
||||
if (strcmp(name, "af") == 0) {
|
||||
return cpu->af;
|
||||
}
|
||||
if (strcmp(name, "pc") == 0) {
|
||||
return cpu->pc;
|
||||
}
|
||||
if (strcmp(name, "sp") == 0) {
|
||||
return cpu->pc;
|
||||
}
|
||||
if (strcmp(name, "f") == 0) {
|
||||
return cpu->f.packed;
|
||||
}
|
||||
if (cliDebugger->system) {
|
||||
uint32_t value = cliDebugger->system->lookupIdentifier(cliDebugger->system, name, dv);
|
||||
if (dv->type != CLIDV_ERROR_TYPE) {
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
dv->type = CLIDV_ERROR_TYPE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger) {
|
||||
debugger->printStatus = _printStatus;
|
||||
debugger->disassemble = NULL;
|
||||
debugger->platformName = "GB-Z80";
|
||||
debugger->platformCommands = NULL;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,14 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef LR35902_CLI_DEBUGGER_H
|
||||
#define LR35902_CLI_DEBUGGER_H
|
||||
|
||||
#include "util/common.h"
|
||||
|
||||
struct CLIDebuggerSystem;
|
||||
void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,101 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "debugger.h"
|
||||
|
||||
#include "lr35902/lr35902.h"
|
||||
#include "core/core.h"
|
||||
|
||||
DEFINE_VECTOR(LR35902DebugBreakpointList, struct LR35902DebugBreakpoint);
|
||||
DEFINE_VECTOR(LR35902DebugWatchpointList, struct LR35902DebugWatchpoint);
|
||||
|
||||
static struct LR35902DebugBreakpoint* _lookupBreakpoint(struct LR35902DebugBreakpointList* breakpoints, uint16_t address) {
|
||||
size_t i;
|
||||
for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) {
|
||||
if (LR35902DebugBreakpointListGetPointer(breakpoints, i)->address == address) {
|
||||
return LR35902DebugBreakpointListGetPointer(breakpoints, i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
|
||||
struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
|
||||
struct LR35902DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->pc - 1);
|
||||
if (!breakpoint) {
|
||||
return;
|
||||
}
|
||||
// TODO: Segments
|
||||
struct mDebuggerEntryInfo info = {
|
||||
.address = breakpoint->address
|
||||
};
|
||||
mDebuggerEnter(d->p, DEBUGGER_ENTER_BREAKPOINT, &info);
|
||||
}
|
||||
|
||||
static void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform);
|
||||
static void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform);
|
||||
|
||||
static void LR35902DebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info);
|
||||
|
||||
static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform*, uint32_t address);
|
||||
static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform*, uint32_t address);
|
||||
static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform*);
|
||||
static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform*);
|
||||
|
||||
struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void) {
|
||||
struct mDebuggerPlatform* platform = malloc(sizeof(struct LR35902Debugger));
|
||||
platform->entered = LR35902DebuggerEnter;
|
||||
platform->init = LR35902DebuggerInit;
|
||||
platform->deinit = LR35902DebuggerDeinit;
|
||||
platform->setBreakpoint = LR35902DebuggerSetBreakpoint;
|
||||
platform->clearBreakpoint = LR35902DebuggerClearBreakpoint;
|
||||
platform->setWatchpoint = NULL;
|
||||
platform->clearWatchpoint = NULL;
|
||||
platform->checkBreakpoints = LR35902DebuggerCheckBreakpoints;
|
||||
platform->hasBreakpoints = LR35902DebuggerHasBreakpoints;
|
||||
return platform;
|
||||
}
|
||||
|
||||
void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform) {
|
||||
struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
|
||||
debugger->cpu = cpu;
|
||||
LR35902DebugBreakpointListInit(&debugger->breakpoints, 0);
|
||||
LR35902DebugWatchpointListInit(&debugger->watchpoints, 0);
|
||||
}
|
||||
|
||||
void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform) {
|
||||
struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
|
||||
LR35902DebugBreakpointListDeinit(&debugger->breakpoints);
|
||||
LR35902DebugWatchpointListDeinit(&debugger->watchpoints);
|
||||
}
|
||||
|
||||
static void LR35902DebuggerEnter(struct mDebuggerPlatform* platform, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
|
||||
struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
|
||||
struct LR35902Core* cpu = debugger->cpu;
|
||||
cpu->nextEvent = cpu->cycles;
|
||||
}
|
||||
|
||||
static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform* d, uint32_t address) {
|
||||
struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
|
||||
struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListAppend(&debugger->breakpoints);
|
||||
breakpoint->address = address;
|
||||
breakpoint->segment = -1;
|
||||
}
|
||||
|
||||
static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform* d, uint32_t address) {
|
||||
struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
|
||||
struct LR35902DebugBreakpointList* breakpoints = &debugger->breakpoints;
|
||||
size_t i;
|
||||
for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) {
|
||||
if (LR35902DebugBreakpointListGetPointer(breakpoints, i)->address == address) {
|
||||
LR35902DebugBreakpointListShift(breakpoints, i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform* d) {
|
||||
struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
|
||||
return LR35902DebugBreakpointListSize(&debugger->breakpoints) || LR35902DebugWatchpointListSize(&debugger->watchpoints);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "debugger/debugger.h"
|
||||
|
||||
struct LR35902DebugBreakpoint {
|
||||
uint16_t address;
|
||||
int segment;
|
||||
};
|
||||
|
||||
struct LR35902DebugWatchpoint {
|
||||
uint16_t address;
|
||||
int segment;
|
||||
enum mWatchpointType type;
|
||||
};
|
||||
|
||||
DECLARE_VECTOR(LR35902DebugBreakpointList, struct LR35902DebugBreakpoint);
|
||||
DECLARE_VECTOR(LR35902DebugWatchpointList, struct LR35902DebugWatchpoint);
|
||||
|
||||
struct LR35902Debugger {
|
||||
struct mDebuggerPlatform d;
|
||||
struct LR35902Core* cpu;
|
||||
|
||||
struct LR35902DebugBreakpointList breakpoints;
|
||||
struct LR35902DebugWatchpointList watchpoints;
|
||||
};
|
||||
|
||||
struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void);
|
Loading…
Reference in New Issue