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