all repos — mgba @ 16608a408cd3f9df010aeef11fb7240e86f1faec

mGBA Game Boy Advance Emulator

src/platform/commandline.c (view raw)

  1#include "commandline.h"
  2
  3#ifdef USE_CLI_DEBUGGER
  4#include "debugger/cli-debugger.h"
  5#endif
  6
  7#ifdef USE_GDB_STUB
  8#include "debugger/gdb-stub.h"
  9#endif
 10
 11#include <fcntl.h>
 12#include <getopt.h>
 13
 14static const char* _defaultFilename = "test.rom";
 15
 16static const struct option _options[] = {
 17	{ "bios", 1, 0, 'b' },
 18	{ "frameskip", 1, 0, 's' },
 19#ifdef USE_CLI_DEBUGGER
 20	{ "debug", 1, 0, 'd' },
 21#endif
 22#ifdef USE_GDB_STUB
 23	{ "gdb", 1, 0, 'g' },
 24#endif
 25	{ 0, 0, 0, 0 }
 26};
 27
 28int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, const char* extraOptions) {
 29	memset(opts, 0, sizeof(*opts));
 30	opts->fd = -1;
 31	opts->biosFd = -1;
 32	opts->width = 240;
 33	opts->height = 160;
 34
 35	int multiplier = 1;
 36	int ch;
 37	char options[64] =
 38		"b:s:"
 39#ifdef USE_CLI_DEBUGGER
 40		"d"
 41#endif
 42#ifdef USE_GDB_STUB
 43		"g"
 44#endif
 45	;
 46	if (extraOptions) {
 47		// TODO: modularize options to subparsers
 48		strncat(options, extraOptions, sizeof(options) - strlen(options) - 1);
 49	}
 50	while ((ch = getopt_long(argc, argv, options, _options, 0)) != -1) {
 51		switch (ch) {
 52		case 'b':
 53			opts->biosFd = open(optarg, O_RDONLY);
 54			break;
 55#ifdef USE_CLI_DEBUGGER
 56		case 'd':
 57			if (opts->debuggerType != DEBUGGER_NONE) {
 58				return 0;
 59			}
 60			opts->debuggerType = DEBUGGER_CLI;
 61			break;
 62#endif
 63		case 'f':
 64			opts->fullscreen = 1;
 65			break;
 66#ifdef USE_GDB_STUB
 67		case 'g':
 68			if (opts->debuggerType != DEBUGGER_NONE) {
 69				return 0;
 70			}
 71			opts->debuggerType = DEBUGGER_GDB;
 72			break;
 73#endif
 74		case 's':
 75			opts->frameskip = atoi(optarg);
 76			break;
 77		case 'S':
 78			opts->perfDuration = atoi(optarg);
 79			break;
 80		case '2':
 81			if (multiplier != 1) {
 82				return 0;
 83			}
 84			multiplier = 2;
 85			break;
 86		case '3':
 87			if (multiplier != 1) {
 88				return 0;
 89			}
 90			multiplier = 3;
 91			break;
 92		case '4':
 93			if (multiplier != 1) {
 94				return 0;
 95			}
 96			multiplier = 4;
 97			break;
 98		default:
 99			return 0;
100		}
101	}
102	argc -= optind;
103	argv += optind;
104	if (argc == 1) {
105		opts->fname = argv[0];
106	} else if (argc == 0) {
107		opts->fname = _defaultFilename;
108	} else {
109		return 0;
110	}
111	opts->fd = open(opts->fname, O_RDONLY);
112	opts->width *= multiplier;
113	opts->height *= multiplier;
114	return 1;
115}
116
117struct ARMDebugger* createDebugger(struct StartupOptions* opts) {
118	union DebugUnion {
119		struct ARMDebugger d;
120#ifdef USE_CLI_DEBUGGER
121		struct CLIDebugger cli;
122#endif
123#ifdef USE_GDB_STUB
124		struct GDBStub gdb;
125#endif
126	};
127
128	union DebugUnion* debugger = malloc(sizeof(union DebugUnion));
129
130	switch (opts->debuggerType) {
131#ifdef USE_CLI_DEBUGGER
132	case DEBUGGER_CLI:
133		CLIDebuggerCreate(&debugger->cli);
134		break;
135#endif
136#ifdef USE_GDB_STUB
137	case DEBUGGER_GDB:
138		GDBStubCreate(&debugger->gdb);
139		GDBStubListen(&debugger->gdb, 2345, 0);
140		break;
141#endif
142	case DEBUGGER_NONE:
143	case DEBUGGER_MAX:
144		free(debugger);
145		return 0;
146		break;
147	}
148
149	return &debugger->d;
150}
151
152void usage(const char* arg0, const char* extraOptions) {
153	printf("usage: %s [option ...] file\n", arg0);
154	puts("\nGeneric options:");
155	puts("  -b, --bios FILE  GBA BIOS file to use");
156#ifdef USE_CLI_DEBUGGER
157	puts("  -d, --debug      Use command-line debugger");
158#endif
159#ifdef USE_GDB_STUB
160	puts("  -g, --gdb        Start GDB session (default port 2345)");
161#endif
162	if (extraOptions) {
163		puts(extraOptions);
164	}
165}