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}