all repos — mgba @ 4b4be372c0ff200e2da2e2855bc942a08e544618

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