all repos — mgba @ 5d8403f5a3deb02c08f46ccb1e179a807f0e0a69

mGBA Game Boy Advance Emulator

src/gb/debugger/cli.c (view raw)

  1/* Copyright (c) 2013-2016 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba/internal/gb/extra/cli.h>
  7
  8#include <mgba/core/core.h>
  9#include <mgba/core/serialize.h>
 10#include <mgba/internal/gb/gb.h>
 11#include <mgba/internal/gb/io.h>
 12#include <mgba/internal/gb/video.h>
 13#include <mgba/internal/lr35902/debugger/cli-debugger.h>
 14
 15static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*);
 16static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem*);
 17static uint32_t _GBCLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);
 18
 19static void _frame(struct CLIDebugger*, struct CLIDebugVector*);
 20static void _load(struct CLIDebugger*, struct CLIDebugVector*);
 21static void _save(struct CLIDebugger*, struct CLIDebugVector*);
 22
 23struct CLIDebuggerCommandSummary _GBCLIDebuggerCommands[] = {
 24	{ "frame", _frame, "", "Frame advance" },
 25	{ "load", _load, "*", "Load a savestate" },
 26	{ "save", _save, "*", "Save a savestate" },
 27	{ 0, 0, 0, 0 }
 28};
 29
 30struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore* core) {
 31	UNUSED(core);
 32	struct GBCLIDebugger* debugger = malloc(sizeof(struct GBCLIDebugger));
 33	LR35902CLIDebuggerCreate(&debugger->d);
 34	debugger->d.init = _GBCLIDebuggerInit;
 35	debugger->d.deinit = NULL;
 36	debugger->d.custom = _GBCLIDebuggerCustom;
 37	debugger->d.lookupIdentifier = _GBCLIDebuggerLookupIdentifier;
 38
 39	debugger->d.name = "Game Boy";
 40	debugger->d.commands = _GBCLIDebuggerCommands;
 41
 42	debugger->core = core;
 43
 44	return &debugger->d;
 45}
 46
 47static void _GBCLIDebuggerInit(struct CLIDebuggerSystem* debugger) {
 48	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger;
 49
 50	gbDebugger->frameAdvance = false;
 51}
 52
 53static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem* debugger) {
 54	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger;
 55
 56	if (gbDebugger->frameAdvance) {
 57		if (!gbDebugger->inVblank && GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1) {
 58			mDebuggerEnter(&gbDebugger->d.p->d, DEBUGGER_ENTER_MANUAL, 0);
 59			gbDebugger->frameAdvance = false;
 60			return false;
 61		}
 62		gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1;
 63		return true;
 64	}
 65	return false;
 66}
 67
 68static uint32_t _GBCLIDebuggerLookupIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) {
 69	UNUSED(debugger);
 70	int i;
 71	for (i = 0; i < REG_MAX; ++i) {
 72		const char* reg = GBIORegisterNames[i];
 73		if (reg && strcasecmp(reg, name) == 0) {
 74			return GB_BASE_IO | i;
 75		}
 76	}
 77	dv->type = CLIDV_ERROR_TYPE;
 78	return 0;
 79}
 80
 81static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
 82	UNUSED(dv);
 83	debugger->d.state = DEBUGGER_CUSTOM;
 84
 85	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
 86	gbDebugger->frameAdvance = true;
 87	gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1;
 88}
 89
 90static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
 91	struct CLIDebuggerBackend* be = debugger->backend;
 92	if (!dv || dv->type != CLIDV_INT_TYPE) {
 93		be->printf(be, "%s\n", ERROR_MISSING_ARGS);
 94		return;
 95	}
 96
 97	int state = dv->intValue;
 98	if (state < 1 || state > 9) {
 99		be->printf(be, "State %u out of range", state);
100	}
101
102	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
103
104	mCoreLoadState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC);
105}
106
107static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
108	struct CLIDebuggerBackend* be = debugger->backend;
109	if (!dv || dv->type != CLIDV_INT_TYPE) {
110		be->printf(be, "%s\n", ERROR_MISSING_ARGS);
111		return;
112	}
113
114	int state = dv->intValue;
115	if (state < 1 || state > 9) {
116		be->printf(be, "State %u out of range", state);
117	}
118
119	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
120
121	mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA);
122}