Debugger: Begin GB debugger

This commit is contained in:
Jeffrey Pfau 2016-04-25 22:34:14 -07:00
parent 1cc0bdeec1
commit b365628aad
9 changed files with 343 additions and 10 deletions

31
src/gb/cli.c Normal file
View File

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

15
src/gb/cli.h Normal file
View File

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

View File

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

View File

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

View File

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

100
src/lr35902/cli-debugger.c Normal file
View File

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

View File

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

101
src/lr35902/debugger.c Normal file
View File

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

30
src/lr35902/debugger.h Normal file
View File

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