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}