mirror of https://github.com/mgba-emu/mgba.git
Use subparsers instead of stuffing everything into one parser
This commit is contained in:
parent
6ca25e44aa
commit
12e5425b9b
|
@ -13,6 +13,14 @@
|
|||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#define GRAPHICS_OPTIONS "234f"
|
||||
#define GRAPHICS_USAGE \
|
||||
"\nGraphics options:\n" \
|
||||
" -2 2x viewport\n" \
|
||||
" -3 3x viewport\n" \
|
||||
" -4 4x viewport\n" \
|
||||
" -f Sart full-screen"
|
||||
|
||||
static const char* _defaultFilename = "test.rom";
|
||||
|
||||
static const struct option _options[] = {
|
||||
|
@ -27,14 +35,13 @@ static const struct option _options[] = {
|
|||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, const char* extraOptions) {
|
||||
int _parseGraphicsArg(struct SubParser* parser, int option, const char* arg);
|
||||
|
||||
int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, struct SubParser* subparser) {
|
||||
memset(opts, 0, sizeof(*opts));
|
||||
opts->fd = -1;
|
||||
opts->biosFd = -1;
|
||||
opts->width = 240;
|
||||
opts->height = 160;
|
||||
|
||||
int multiplier = 1;
|
||||
int ch;
|
||||
char options[64] =
|
||||
"b:s:"
|
||||
|
@ -45,9 +52,9 @@ int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, c
|
|||
"g"
|
||||
#endif
|
||||
;
|
||||
if (extraOptions) {
|
||||
if (subparser->extraOptions) {
|
||||
// TODO: modularize options to subparsers
|
||||
strncat(options, extraOptions, sizeof(options) - strlen(options) - 1);
|
||||
strncat(options, subparser->extraOptions, sizeof(options) - strlen(options) - 1);
|
||||
}
|
||||
while ((ch = getopt_long(argc, argv, options, _options, 0)) != -1) {
|
||||
switch (ch) {
|
||||
|
@ -62,9 +69,6 @@ int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, c
|
|||
opts->debuggerType = DEBUGGER_CLI;
|
||||
break;
|
||||
#endif
|
||||
case 'f':
|
||||
opts->fullscreen = 1;
|
||||
break;
|
||||
#ifdef USE_GDB_STUB
|
||||
case 'g':
|
||||
if (opts->debuggerType != DEBUGGER_NONE) {
|
||||
|
@ -76,31 +80,15 @@ int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, c
|
|||
case 's':
|
||||
opts->frameskip = atoi(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
opts->perfDuration = atoi(optarg);
|
||||
break;
|
||||
case '2':
|
||||
if (multiplier != 1) {
|
||||
return 0;
|
||||
}
|
||||
multiplier = 2;
|
||||
break;
|
||||
case '3':
|
||||
if (multiplier != 1) {
|
||||
return 0;
|
||||
}
|
||||
multiplier = 3;
|
||||
break;
|
||||
case '4':
|
||||
if (multiplier != 1) {
|
||||
return 0;
|
||||
}
|
||||
multiplier = 4;
|
||||
break;
|
||||
default:
|
||||
if (subparser) {
|
||||
if (!subparser->parse(subparser, ch, optarg)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc == 1) {
|
||||
|
@ -111,11 +99,55 @@ int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, c
|
|||
return 0;
|
||||
}
|
||||
opts->fd = open(opts->fname, O_RDONLY);
|
||||
opts->width *= multiplier;
|
||||
opts->height *= multiplier;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts) {
|
||||
parser->usage = GRAPHICS_USAGE;
|
||||
parser->opts = opts;
|
||||
parser->parse = _parseGraphicsArg;
|
||||
parser->extraOptions = GRAPHICS_OPTIONS;
|
||||
opts->multiplier = 1;
|
||||
opts->fullscreen = 0;
|
||||
opts->width = 240;
|
||||
opts->height = 160;
|
||||
}
|
||||
|
||||
int _parseGraphicsArg(struct SubParser* parser, int option, const char* arg) {
|
||||
struct GraphicsOpts* graphicsOpts = parser->opts;
|
||||
switch (option) {
|
||||
case 'f':
|
||||
graphicsOpts->fullscreen = 1;
|
||||
return 1;
|
||||
case '2':
|
||||
if (graphicsOpts->multiplier != 1) {
|
||||
return 0;
|
||||
}
|
||||
graphicsOpts->multiplier = 2;
|
||||
graphicsOpts->width *= graphicsOpts->multiplier;
|
||||
graphicsOpts->height *= graphicsOpts->multiplier;
|
||||
return 1;
|
||||
case '3':
|
||||
if (graphicsOpts->multiplier != 1) {
|
||||
return 0;
|
||||
}
|
||||
graphicsOpts->multiplier = 3;
|
||||
graphicsOpts->width *= graphicsOpts->multiplier;
|
||||
graphicsOpts->height *= graphicsOpts->multiplier;
|
||||
return 1;
|
||||
case '4':
|
||||
if (graphicsOpts->multiplier != 1) {
|
||||
return 0;
|
||||
}
|
||||
graphicsOpts->multiplier = 4;
|
||||
graphicsOpts->width *= graphicsOpts->multiplier;
|
||||
graphicsOpts->height *= graphicsOpts->multiplier;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct ARMDebugger* createDebugger(struct StartupOptions* opts) {
|
||||
union DebugUnion {
|
||||
struct ARMDebugger d;
|
||||
|
|
|
@ -14,19 +14,6 @@ enum DebuggerType {
|
|||
DEBUGGER_MAX
|
||||
};
|
||||
|
||||
#define GRAPHICS_OPTIONS "234f"
|
||||
#define GRAPHICS_USAGE \
|
||||
"\nGraphics options:\n" \
|
||||
" -2 2x viewport\n" \
|
||||
" -3 3x viewport\n" \
|
||||
" -4 4x viewport\n" \
|
||||
" -f Sart full-screen"
|
||||
|
||||
#define PERF_OPTIONS "S:"
|
||||
#define PERF_USAGE \
|
||||
"\nBenchmark options:\n" \
|
||||
" -S SEC Run for SEC in-game seconds before exiting"
|
||||
|
||||
struct StartupOptions {
|
||||
int fd;
|
||||
const char* fname;
|
||||
|
@ -35,19 +22,28 @@ struct StartupOptions {
|
|||
int rewindBufferCapacity;
|
||||
int rewindBufferInterval;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int fullscreen;
|
||||
|
||||
int perfDuration;
|
||||
|
||||
enum DebuggerType debuggerType;
|
||||
int debugAtStart;
|
||||
};
|
||||
|
||||
int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, const char* extraOptions);
|
||||
struct SubParser {
|
||||
const char* usage;
|
||||
int (*parse)(struct SubParser* parser, int option, const char* arg);
|
||||
const char* extraOptions;
|
||||
void* opts;
|
||||
};
|
||||
|
||||
struct GraphicsOpts {
|
||||
int multiplier;
|
||||
int fullscreen;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, struct SubParser* subparser);
|
||||
void usage(const char* arg0, const char* extraOptions);
|
||||
|
||||
void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts);
|
||||
struct ARMDebugger* createDebugger(struct StartupOptions* opts);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,12 +2,23 @@
|
|||
#include "gba.h"
|
||||
#include "renderers/video-software.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define PERF_OPTIONS "S:"
|
||||
#define PERF_USAGE \
|
||||
"\nBenchmark options:\n" \
|
||||
" -S SEC Run for SEC in-game seconds before exiting"
|
||||
|
||||
struct PerfOpts {
|
||||
int duration;
|
||||
};
|
||||
|
||||
static void _GBAPerfRunloop(struct GBAThread* context, int* frames);
|
||||
static void _GBAPerfShutdown(int signal);
|
||||
static int _parsePerfOpts(struct SubParser* parser, int option, const char* arg);
|
||||
|
||||
static struct GBAThread* _thread;
|
||||
|
||||
|
@ -17,8 +28,16 @@ int main(int argc, char** argv) {
|
|||
struct GBAVideoSoftwareRenderer renderer;
|
||||
GBAVideoSoftwareRendererCreate(&renderer);
|
||||
|
||||
struct PerfOpts perfOpts = {};
|
||||
struct SubParser subparser = {
|
||||
.usage = PERF_USAGE,
|
||||
.parse = _parsePerfOpts,
|
||||
.extraOptions = PERF_OPTIONS,
|
||||
.opts = &perfOpts
|
||||
};
|
||||
|
||||
struct StartupOptions opts;
|
||||
if (!parseCommandArgs(&opts, argc, argv, PERF_OPTIONS)) {
|
||||
if (!parseCommandArgs(&opts, argc, argv, &subparser)) {
|
||||
usage(argv[0], PERF_USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
@ -39,7 +58,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
GBAThreadStart(&context);
|
||||
|
||||
int frames = opts.perfDuration;
|
||||
int frames = perfOpts.duration;
|
||||
time_t start = time(0);
|
||||
_GBAPerfRunloop(&context, &frames);
|
||||
time_t end = time(0);
|
||||
|
@ -96,3 +115,14 @@ static void _GBAPerfShutdown(int signal) {
|
|||
_thread->state = THREAD_EXITING;
|
||||
pthread_mutex_unlock(&_thread->stateMutex);
|
||||
}
|
||||
|
||||
static int _parsePerfOpts(struct SubParser* parser, int option, const char* arg) {
|
||||
struct PerfOpts* opts = parser->opts;
|
||||
switch (option) {
|
||||
case 'S':
|
||||
opts->duration = strtol(arg, 0, 10);
|
||||
return !errno;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,15 +62,18 @@ int main(int argc, char** argv) {
|
|||
GBAVideoSoftwareRendererCreate(&renderer.d);
|
||||
|
||||
struct StartupOptions opts;
|
||||
if (!parseCommandArgs(&opts, argc, argv, GRAPHICS_OPTIONS)) {
|
||||
usage(argv[0], GRAPHICS_USAGE);
|
||||
struct SubParser subparser;
|
||||
struct GraphicsOpts graphicsOpts;
|
||||
initParserForGraphics(&subparser, &graphicsOpts);
|
||||
if (!parseCommandArgs(&opts, argc, argv, &subparser)) {
|
||||
usage(argv[0], subparser.usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
renderer.viewportWidth = opts.width;
|
||||
renderer.viewportHeight = opts.height;
|
||||
renderer.viewportWidth = graphicsOpts.width;
|
||||
renderer.viewportHeight = graphicsOpts.height;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
renderer.events.fullscreen = opts.fullscreen;
|
||||
renderer.events.fullscreen = graphicsOpts.fullscreen;
|
||||
#endif
|
||||
|
||||
if (!_GBASDLInit(&renderer)) {
|
||||
|
|
|
@ -49,13 +49,16 @@ int main(int argc, char** argv) {
|
|||
GBAVideoSoftwareRendererCreate(&renderer.d);
|
||||
|
||||
struct StartupOptions opts;
|
||||
if (!parseCommandArgs(&opts, argc, argv, GRAPHICS_OPTIONS)) {
|
||||
usage(argv[0], GRAPHICS_USAGE);
|
||||
struct SubParser subparser;
|
||||
struct GraphicsOpts graphicsOpts;
|
||||
initParserForGraphics(&subparser, &graphicsOpts);
|
||||
if (!parseCommandArgs(&opts, argc, argv, &subparser)) {
|
||||
usage(argv[0], subparser.usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
renderer.viewportWidth = opts.width;
|
||||
renderer.viewportHeight = opts.height;
|
||||
renderer.viewportWidth = graphicsOpts.width;
|
||||
renderer.viewportHeight = graphicsOpts.height;
|
||||
|
||||
if (!_GBASDLInit(&renderer)) {
|
||||
return 1;
|
||||
|
@ -75,7 +78,7 @@ int main(int argc, char** argv) {
|
|||
GBAMapOptionsToContext(&opts, &context);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
renderer.events.fullscreen = opts.fullscreen;
|
||||
renderer.events.fullscreen = graphicsOpts.fullscreen;
|
||||
renderer.window = SDL_CreateWindow("GBAc", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer.viewportWidth, renderer.viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer.events.fullscreen));
|
||||
SDL_GetWindowSize(renderer.window, &renderer.viewportWidth, &renderer.viewportHeight);
|
||||
renderer.events.window = renderer.window;
|
||||
|
@ -100,7 +103,7 @@ int main(int argc, char** argv) {
|
|||
SDL_Surface* surface = SDL_GetVideoSurface();
|
||||
SDL_LockSurface(surface);
|
||||
|
||||
renderer.ratio = renderer.viewportWidth / VIDEO_HORIZONTAL_PIXELS;
|
||||
renderer.ratio = graphicsOpts.multiplier;
|
||||
if (renderer.ratio == 1) {
|
||||
renderer.d.outputBuffer = surface->pixels;
|
||||
#ifdef COLOR_16_BIT
|
||||
|
|
Loading…
Reference in New Issue