all repos — mgba @ 4c38f769565e8ddd7d3a8eef1a41975206c129a0

mGBA Game Boy Advance Emulator

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