all repos — mgba @ 7149dd3102a6bbb7f73cae7da0c01dc784b0f601

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