all repos — mgba @ 9dc49df0bca23925cfcc8193a1770463fd9916cf

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