all repos — mgba @ 65a8a4e76be5cb06255faf99432de1145ade396d

mGBA Game Boy Advance Emulator

src/platform/commandline.c (view raw)

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