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