all repos — mgba @ c39162732d966e379c68a11fed6371276c3f9eb5

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