Use subparsers instead of stuffing everything into one parser

This commit is contained in:
Jeffrey Pfau 2014-04-26 16:05:09 -07:00
parent 6ca25e44aa
commit 12e5425b9b
5 changed files with 130 additions and 66 deletions

View File

@ -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,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;

View File

@ -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

View File

@ -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;
}
}

View File

@ -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)) {

View File

@ -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