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