all repos — mgba @ a0d223eef7c33382231510db9c851f856c891323

mGBA Game Boy Advance Emulator

src/gba/extra/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 "cli.h"
  7
  8#include "arm/debugger/cli-debugger.h"
  9#include "core/serialize.h"
 10#include "gba/io.h"
 11#include "gba/serialize.h"
 12
 13static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*);
 14static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem*);
 15static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);
 16
 17static void _frame(struct CLIDebugger*, struct CLIDebugVector*);
 18static void _load(struct CLIDebugger*, struct CLIDebugVector*);
 19static void _save(struct CLIDebugger*, struct CLIDebugVector*);
 20
 21struct CLIDebuggerCommandSummary _GBACLIDebuggerCommands[] = {
 22	{ "frame", _frame, 0, "Frame advance" },
 23	{ "load", _load, CLIDVParse, "Load a savestate" },
 24	{ "save", _save, CLIDVParse, "Save a savestate" },
 25	{ 0, 0, 0, 0 }
 26};
 27
 28struct GBACLIDebugger* GBACLIDebuggerCreate(struct mCore* core) {
 29	struct GBACLIDebugger* debugger = malloc(sizeof(struct GBACLIDebugger));
 30	ARMCLIDebuggerCreate(&debugger->d);
 31	debugger->d.init = _GBACLIDebuggerInit;
 32	debugger->d.deinit = NULL;
 33	debugger->d.custom = _GBACLIDebuggerCustom;
 34	debugger->d.lookupIdentifier = _GBACLIDebuggerLookupIdentifier;
 35
 36	debugger->d.name = "Game Boy Advance";
 37	debugger->d.commands = _GBACLIDebuggerCommands;
 38
 39	debugger->core = core;
 40
 41	return debugger;
 42}
 43
 44static void _GBACLIDebuggerInit(struct CLIDebuggerSystem* debugger) {
 45	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger;
 46
 47	gbaDebugger->frameAdvance = false;
 48}
 49
 50static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem* debugger) {
 51	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger;
 52
 53	if (gbaDebugger->frameAdvance) {
 54		if (!gbaDebugger->inVblank && GBARegisterDISPSTATIsInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1])) {
 55			mDebuggerEnter(&gbaDebugger->d.p->d, DEBUGGER_ENTER_MANUAL, 0);
 56			gbaDebugger->frameAdvance = false;
 57			return false;
 58		}
 59		gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1]);
 60		return true;
 61	}
 62	return false;
 63}
 64
 65static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) {
 66	UNUSED(debugger);
 67	int i;
 68	for (i = 0; i < REG_MAX; i += 2) {
 69		const char* reg = GBAIORegisterNames[i >> 1];
 70		if (reg && strcasecmp(reg, name) == 0) {
 71			return BASE_IO | i;
 72		}
 73	}
 74	dv->type = CLIDV_ERROR_TYPE;
 75	return 0;
 76}
 77
 78static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
 79	UNUSED(dv);
 80	debugger->d.state = DEBUGGER_CUSTOM;
 81
 82	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;
 83	gbaDebugger->frameAdvance = true;
 84	gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1]);
 85}
 86
 87static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
 88	struct CLIDebuggerBackend* be = debugger->backend;
 89	if (!dv || dv->type != CLIDV_INT_TYPE) {
 90		be->printf(be, "%s\n", ERROR_MISSING_ARGS);
 91		return;
 92	}
 93
 94	int state = dv->intValue;
 95	if (state < 1 || state > 9) {
 96		be->printf(be, "State %u out of range", state);
 97	}
 98
 99	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;
100
101	mCoreLoadState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT);
102}
103
104// TODO: Put back rewind
105
106static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
107	struct CLIDebuggerBackend* be = debugger->backend;
108	if (!dv || dv->type != CLIDV_INT_TYPE) {
109		be->printf(be, "%s\n", ERROR_MISSING_ARGS);
110		return;
111	}
112
113	int state = dv->intValue;
114	if (state < 1 || state > 9) {
115		be->printf(be, "State %u out of range", state);
116	}
117
118	struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;
119
120	mCoreSaveState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT);
121}