all repos — mgba @ 4bd35550455e74a870a52c611d8e39d4dde20015

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