src/gb/debugger/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 <mgba/internal/gb/extra/cli.h>
7
8#include <mgba/core/core.h>
9#include <mgba/core/serialize.h>
10#include <mgba/internal/gb/gb.h>
11#include <mgba/internal/gb/io.h>
12#include <mgba/internal/gb/video.h>
13#include <mgba/internal/sm83/debugger/cli-debugger.h>
14
15static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*);
16static bool _GBCLIDebuggerCustom(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 _GBCLIDebuggerCommands[] = {
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 CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore* core) {
34 UNUSED(core);
35 struct GBCLIDebugger* debugger = malloc(sizeof(struct GBCLIDebugger));
36 SM83CLIDebuggerCreate(&debugger->d);
37 debugger->d.init = _GBCLIDebuggerInit;
38 debugger->d.deinit = NULL;
39 debugger->d.custom = _GBCLIDebuggerCustom;
40
41 debugger->d.name = "Game Boy";
42 debugger->d.commands = _GBCLIDebuggerCommands;
43 debugger->d.commandAliases = NULL;
44
45 debugger->core = core;
46
47 return &debugger->d;
48}
49
50static void _GBCLIDebuggerInit(struct CLIDebuggerSystem* debugger) {
51 struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger;
52
53 gbDebugger->frameAdvance = false;
54}
55
56static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem* debugger) {
57 struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger;
58
59 if (gbDebugger->frameAdvance) {
60 if (!gbDebugger->inVblank && GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1) {
61 mDebuggerEnter(&gbDebugger->d.p->d, DEBUGGER_ENTER_MANUAL, 0);
62 gbDebugger->frameAdvance = false;
63 return false;
64 }
65 gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1;
66 return true;
67 }
68 return true;
69}
70
71static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
72 UNUSED(dv);
73 debugger->d.state = DEBUGGER_CALLBACK;
74
75 struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
76 gbDebugger->frameAdvance = true;
77 gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1;
78}
79
80#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
81static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
82 struct CLIDebuggerBackend* be = debugger->backend;
83 if (!dv || dv->type != CLIDV_INT_TYPE) {
84 be->printf(be, "%s\n", ERROR_MISSING_ARGS);
85 return;
86 }
87
88 int state = dv->intValue;
89 if (state < 1 || state > 9) {
90 be->printf(be, "State %u out of range", state);
91 }
92
93 struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
94
95 mCoreLoadState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC);
96}
97
98static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
99 struct CLIDebuggerBackend* be = debugger->backend;
100 if (!dv || dv->type != CLIDV_INT_TYPE) {
101 be->printf(be, "%s\n", ERROR_MISSING_ARGS);
102 return;
103 }
104
105 int state = dv->intValue;
106 if (state < 1 || state > 9) {
107 be->printf(be, "State %u out of range", state);
108 }
109
110 struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
111
112 mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA);
113}
114#endif