all repos — mgba @ 93e5b6da7b69d94bbe2e0783f05897b1adee755b

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