all repos — mgba @ 21a23b3a7a862180dd057321c5fb317c7d9865c4

mGBA Game Boy Advance Emulator

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

  1/* Copyright (c) 2013-2015 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/gba/extra/cli.h>
  7
  8#include <mgba/core/core.h>
  9#include <mgba/core/serialize.h>
 10#include <mgba/internal/gba/gba.h>
 11#include <mgba/internal/gba/io.h>
 12#include <mgba/internal/gba/video.h>
 13#include <mgba/internal/arm/debugger/cli-debugger.h>
 14
 15static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*);
 16static bool _GBACLIDebuggerCustom(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 _GBACLIDebuggerCommands[] = {
 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 GBACLIDebugger* GBACLIDebuggerCreate(struct mCore* core) {
 34	struct GBACLIDebugger* debugger = malloc(sizeof(struct GBACLIDebugger));
 35	ARMCLIDebuggerCreate(&debugger->d);
 36	debugger->d.init = _GBACLIDebuggerInit;
 37	debugger->d.deinit = NULL;
 38	debugger->d.custom = _GBACLIDebuggerCustom;
 39
 40	debugger->d.name = "Game Boy Advance";
 41	debugger->d.commands = _GBACLIDebuggerCommands;
 42	debugger->d.commandAliases = NULL;
 43
 44	debugger->core = core;
 45
 46	return debugger;
 47}
 48
 49static void _GBACLIDebuggerInit(struct CLIDebuggerSystem* debugger) {
 50	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger;
 51
 52	gbaDebugger->frameAdvance = false;
 53}
 54
 55static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem* debugger) {
 56	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger;
 57
 58	if (gbaDebugger->frameAdvance) {
 59		if (!gbaDebugger->inVblank && GBARegisterDISPSTATIsInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1])) {
 60			mDebuggerEnter(&gbaDebugger->d.p->d, DEBUGGER_ENTER_MANUAL, 0);
 61			gbaDebugger->frameAdvance = false;
 62			return false;
 63		}
 64		gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1]);
 65		return true;
 66	}
 67	return true;
 68}
 69
 70static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
 71	UNUSED(dv);
 72	debugger->d.state = DEBUGGER_CALLBACK;
 73
 74	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;
 75	gbaDebugger->frameAdvance = true;
 76	gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1]);
 77}
 78
 79#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
 80static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
 81	struct CLIDebuggerBackend* be = debugger->backend;
 82	if (!dv || dv->type != CLIDV_INT_TYPE) {
 83		be->printf(be, "%s\n", ERROR_MISSING_ARGS);
 84		return;
 85	}
 86
 87	int state = dv->intValue;
 88	if (state < 1 || state > 9) {
 89		be->printf(be, "State %u out of range", state);
 90	}
 91
 92	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;
 93
 94	mCoreLoadState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC);
 95}
 96
 97// TODO: Put back rewind
 98
 99static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
100	struct CLIDebuggerBackend* be = debugger->backend;
101	if (!dv || dv->type != CLIDV_INT_TYPE) {
102		be->printf(be, "%s\n", ERROR_MISSING_ARGS);
103		return;
104	}
105
106	int state = dv->intValue;
107	if (state < 1 || state > 9) {
108		be->printf(be, "State %u out of range", state);
109	}
110
111	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;
112
113	mCoreSaveState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA);
114}
115#endif