diff --git a/src/platform/commandline.c b/src/platform/commandline.c index 74fc5058b..47beb526e 100644 --- a/src/platform/commandline.c +++ b/src/platform/commandline.c @@ -13,6 +13,14 @@ #include #include +#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,29 +80,13 @@ 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: - return 0; + if (subparser) { + if (!subparser->parse(subparser, ch, optarg)) { + return 0; + } + } + break; } } argc -= optind; @@ -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; diff --git a/src/platform/commandline.h b/src/platform/commandline.h index 01d53336a..acc529eb4 100644 --- a/src/platform/commandline.h +++ b/src/platform/commandline.h @@ -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 diff --git a/src/platform/perf-main.c b/src/platform/perf-main.c index 770077abf..c554a8e60 100644 --- a/src/platform/perf-main.c +++ b/src/platform/perf-main.c @@ -2,12 +2,23 @@ #include "gba.h" #include "renderers/video-software.h" +#include #include #include #include +#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; + } +} diff --git a/src/platform/sdl/gl-main.c b/src/platform/sdl/gl-main.c index 8493f4462..6af9023fd 100644 --- a/src/platform/sdl/gl-main.c +++ b/src/platform/sdl/gl-main.c @@ -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)) { diff --git a/src/platform/sdl/sw-main.c b/src/platform/sdl/sw-main.c index d0b9239e4..93194fa9b 100644 --- a/src/platform/sdl/sw-main.c +++ b/src/platform/sdl/sw-main.c @@ -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