all repos — mgba @ 659b929f3e58d50762f3054ba634877e458cdb4c

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/sm83/debugger/cli-debugger.h>
 14
 15static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*);
 16static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem*);
 17
 18static void _frame(struct CLIDebugger*, struct CLIDebugVector*);
 19#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
 20static void _load(struct CLIDebugger*, struct CLIDebugVector*);
 21static void _save(struct CLIDebugger*, struct CLIDebugVector*);
 22#endif
 23
 24struct CLIDebuggerCommandSummary _GBCLIDebuggerCommands[] = {
 25	{ "frame", _frame, "", "Frame advance" },
 26#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
 27	{ "load", _load, "*", "Load a savestate" },
 28	{ "save", _save, "*", "Save a savestate" },
 29#endif
 30	{ 0, 0, 0, 0 }
 31};
 32
 33struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore* core) {
 34	UNUSED(core);
 35	struct GBCLIDebugger* debugger = malloc(sizeof(struct GBCLIDebugger));
 36	SM83CLIDebuggerCreate(&debugger->d);
 37	debugger->d.init = _GBCLIDebuggerInit;
 38	debugger->d.deinit = NULL;
 39	debugger->d.custom = _GBCLIDebuggerCustom;
 40
 41	debugger->d.name = "Game Boy";
 42	debugger->d.commands = _GBCLIDebuggerCommands;
 43	debugger->d.commandAliases = NULL;
 44
 45	debugger->core = core;
 46
 47	return &debugger->d;
 48}
 49
 50static void _GBCLIDebuggerInit(struct CLIDebuggerSystem* debugger) {
 51	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger;
 52
 53	gbDebugger->frameAdvance = false;
 54}
 55
 56static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem* debugger) {
 57	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger;
 58
 59	if (gbDebugger->frameAdvance) {
 60		if (!gbDebugger->inVblank && GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1) {
 61			mDebuggerEnter(&gbDebugger->d.p->d, DEBUGGER_ENTER_MANUAL, 0);
 62			gbDebugger->frameAdvance = false;
 63			return false;
 64		}
 65		gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1;
 66		return true;
 67	}
 68	return true;
 69}
 70
 71static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
 72	UNUSED(dv);
 73	debugger->d.state = DEBUGGER_CALLBACK;
 74
 75	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
 76	gbDebugger->frameAdvance = true;
 77	gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1;
 78}
 79
 80#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
 81static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
 82	struct CLIDebuggerBackend* be = debugger->backend;
 83	if (!dv || dv->type != CLIDV_INT_TYPE) {
 84		be->printf(be, "%s\n", ERROR_MISSING_ARGS);
 85		return;
 86	}
 87
 88	int state = dv->intValue;
 89	if (state < 1 || state > 9) {
 90		be->printf(be, "State %u out of range", state);
 91	}
 92
 93	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
 94
 95	mCoreLoadState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC);
 96}
 97
 98static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
 99	struct CLIDebuggerBackend* be = debugger->backend;
100	if (!dv || dv->type != CLIDV_INT_TYPE) {
101		be->printf(be, "%s\n", ERROR_MISSING_ARGS);
102		return;
103	}
104
105	int state = dv->intValue;
106	if (state < 1 || state > 9) {
107		be->printf(be, "State %u out of range", state);
108	}
109
110	struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
111
112	mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA);
113}
114#endif