all repos — mgba @ 37a0839a251b432d2d0bb1ebe70d4aa100008c1d

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