all repos — mgba @ 234ecd961976d7e24609beda22c9db9fafa6901b

mGBA Game Boy Advance Emulator

src/platform/commandline.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 "commandline.h"
  7
  8#include "debugger/debugger.h"
  9
 10#ifdef USE_CLI_DEBUGGER
 11#include "debugger/cli-debugger.h"
 12#include "gba/supervisor/cli.h"
 13#endif
 14
 15#ifdef USE_GDB_STUB
 16#include "debugger/gdb-stub.h"
 17#endif
 18
 19#include "gba/video.h"
 20#include "util/string.h"
 21
 22#include <fcntl.h>
 23#include <getopt.h>
 24
 25#define GRAPHICS_OPTIONS "123456f"
 26#define GRAPHICS_USAGE \
 27	"\nGraphics options:\n" \
 28	"  -1               1x viewport\n" \
 29	"  -2               2x viewport\n" \
 30	"  -3               3x viewport\n" \
 31	"  -4               4x viewport\n" \
 32	"  -5               5x viewport\n" \
 33	"  -6               6x viewport\n" \
 34	"  -f               Start full-screen"
 35
 36static const struct option _options[] = {
 37	{ "bios",      required_argument, 0, 'b' },
 38	{ "cheats",    required_argument, 0, 'c' },
 39	{ "frameskip", required_argument, 0, 's' },
 40#ifdef USE_CLI_DEBUGGER
 41	{ "debug",     no_argument, 0, 'd' },
 42#endif
 43#ifdef USE_GDB_STUB
 44	{ "gdb",       no_argument, 0, 'g' },
 45#endif
 46	{ "help",      no_argument, 0, 'h' },
 47	{ "movie",     required_argument, 0, 'v' },
 48	{ "patch",     required_argument, 0, 'p' },
 49	{ "version",   no_argument, 0, '\0' },
 50	{ 0, 0, 0, 0 }
 51};
 52
 53static bool _parseGraphicsArg(struct SubParser* parser, struct GBAConfig* config, int option, const char* arg);
 54
 55bool parseArguments(struct GBAArguments* opts, struct GBAConfig* config, int argc, char* const* argv, struct SubParser* subparser) {
 56	int ch;
 57	char options[64] =
 58		"b:c:hl:p:s:v:"
 59#ifdef USE_CLI_DEBUGGER
 60		"d"
 61#endif
 62#ifdef USE_GDB_STUB
 63		"g"
 64#endif
 65	;
 66	memset(opts, 0, sizeof(*opts));
 67	if (subparser && subparser->extraOptions) {
 68		// TODO: modularize options to subparsers
 69		strncat(options, subparser->extraOptions, sizeof(options) - strlen(options) - 1);
 70	}
 71	int index = 0;
 72	while ((ch = getopt_long(argc, argv, options, _options, &index)) != -1) {
 73		const struct option* opt = &_options[index];
 74		switch (ch) {
 75		case '\0':
 76			if (strcmp(opt->name, "version") == 0) {
 77				opts->showVersion = true;
 78			} else {
 79				return false;
 80			}
 81			break;
 82		case 'b':
 83			GBAConfigSetOverrideValue(config, "bios", optarg);
 84			break;
 85		case 'c':
 86			opts->cheatsFile = strdup(optarg);
 87			break;
 88#ifdef USE_CLI_DEBUGGER
 89		case 'd':
 90			if (opts->debuggerType != DEBUGGER_NONE) {
 91				return false;
 92			}
 93			opts->debuggerType = DEBUGGER_CLI;
 94			break;
 95#endif
 96#ifdef USE_GDB_STUB
 97		case 'g':
 98			if (opts->debuggerType != DEBUGGER_NONE) {
 99				return false;
100			}
101			opts->debuggerType = DEBUGGER_GDB;
102			break;
103#endif
104		case 'h':
105			opts->showHelp = true;
106			break;
107		case 'l':
108			GBAConfigSetOverrideValue(config, "logLevel", optarg);
109			break;
110		case 'p':
111			opts->patch = strdup(optarg);
112			break;
113		case 's':
114			GBAConfigSetOverrideValue(config, "frameskip", optarg);
115			break;
116		case 'v':
117			opts->movie = strdup(optarg);
118			break;
119		default:
120			if (subparser) {
121				if (!subparser->parse(subparser, config, ch, optarg)) {
122					return false;
123				}
124			}
125			break;
126		}
127	}
128	argc -= optind;
129	argv += optind;
130	if (argc != 1) {
131		return opts->showHelp || opts->showVersion;
132	}
133	opts->fname = strdup(argv[0]);
134	return true;
135}
136
137void freeArguments(struct GBAArguments* opts) {
138	free(opts->fname);
139	opts->fname = 0;
140
141	free(opts->patch);
142	opts->patch = 0;
143
144	free(opts->movie);
145	opts->movie = 0;
146}
147
148void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts) {
149	parser->usage = GRAPHICS_USAGE;
150	parser->opts = opts;
151	parser->parse = _parseGraphicsArg;
152	parser->extraOptions = GRAPHICS_OPTIONS;
153	opts->multiplier = 0;
154	opts->fullscreen = false;
155}
156
157bool _parseGraphicsArg(struct SubParser* parser, struct GBAConfig* config, int option, const char* arg) {
158	UNUSED(arg);
159	struct GraphicsOpts* graphicsOpts = parser->opts;
160	switch (option) {
161	case 'f':
162		graphicsOpts->fullscreen = true;
163		GBAConfigSetOverrideIntValue(config, "fullscreen", 1);
164		return true;
165	case '1':
166	case '2':
167	case '3':
168	case '4':
169	case '5':
170	case '6':
171		if (graphicsOpts->multiplier) {
172			return false;
173		}
174		graphicsOpts->multiplier = option - '0';
175		GBAConfigSetOverrideIntValue(config, "width", VIDEO_HORIZONTAL_PIXELS * graphicsOpts->multiplier);
176		GBAConfigSetOverrideIntValue(config, "height", VIDEO_VERTICAL_PIXELS * graphicsOpts->multiplier);
177		return true;
178	default:
179		return false;
180	}
181}
182
183struct ARMDebugger* createDebugger(struct GBAArguments* opts, struct GBAThread* context) {
184#ifndef USE_CLI_DEBUGGER
185	UNUSED(context);
186#endif
187	union DebugUnion {
188		struct ARMDebugger d;
189#ifdef USE_CLI_DEBUGGER
190		struct CLIDebugger cli;
191#endif
192#ifdef USE_GDB_STUB
193		struct GDBStub gdb;
194#endif
195	};
196
197	union DebugUnion* debugger = malloc(sizeof(union DebugUnion));
198
199	switch (opts->debuggerType) {
200#ifdef USE_CLI_DEBUGGER
201	case DEBUGGER_CLI:
202		CLIDebuggerCreate(&debugger->cli);
203		struct GBACLIDebugger* gbaDebugger = GBACLIDebuggerCreate(context);
204		CLIDebuggerAttachSystem(&debugger->cli, &gbaDebugger->d);
205		break;
206#endif
207#ifdef USE_GDB_STUB
208	case DEBUGGER_GDB:
209		GDBStubCreate(&debugger->gdb);
210		GDBStubListen(&debugger->gdb, 2345, 0);
211		break;
212#endif
213	case DEBUGGER_NONE:
214	case DEBUGGER_MAX:
215		free(debugger);
216		return 0;
217		break;
218	}
219
220	return &debugger->d;
221}
222
223void usage(const char* arg0, const char* extraOptions) {
224	printf("usage: %s [option ...] file\n", arg0);
225	puts("\nGeneric options:");
226	puts("  -b, --bios FILE     GBA BIOS file to use");
227	puts("  -c, --cheats FILE   Apply cheat codes from a file");
228#ifdef USE_CLI_DEBUGGER
229	puts("  -d, --debug         Use command-line debugger");
230#endif
231#ifdef USE_GDB_STUB
232	puts("  -g, --gdb           Start GDB session (default port 2345)");
233#endif
234	puts("  -v, --movie FILE    Play back a movie of recorded input");
235	puts("  -p, --patch FILE    Apply a specified patch file when running");
236	puts("  -s, --frameskip N   Skip every N frames");
237	puts("  --version           Print version and exit");
238	if (extraOptions) {
239		puts(extraOptions);
240	}
241}
242
243void version(const char* arg0) {
244	printf("%s %s (%s)\n", arg0, projectVersion, gitCommit);
245}