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 <fcntl.h>
|
||||||
#include <getopt.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 char* _defaultFilename = "test.rom";
|
||||||
|
|
||||||
static const struct option _options[] = {
|
static const struct option _options[] = {
|
||||||
|
@ -27,14 +35,13 @@ static const struct option _options[] = {
|
||||||
{ 0, 0, 0, 0 }
|
{ 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));
|
memset(opts, 0, sizeof(*opts));
|
||||||
opts->fd = -1;
|
opts->fd = -1;
|
||||||
opts->biosFd = -1;
|
opts->biosFd = -1;
|
||||||
opts->width = 240;
|
|
||||||
opts->height = 160;
|
|
||||||
|
|
||||||
int multiplier = 1;
|
|
||||||
int ch;
|
int ch;
|
||||||
char options[64] =
|
char options[64] =
|
||||||
"b:s:"
|
"b:s:"
|
||||||
|
@ -45,9 +52,9 @@ int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, c
|
||||||
"g"
|
"g"
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
if (extraOptions) {
|
if (subparser->extraOptions) {
|
||||||
// TODO: modularize options to subparsers
|
// 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) {
|
while ((ch = getopt_long(argc, argv, options, _options, 0)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
@ -62,9 +69,6 @@ int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, c
|
||||||
opts->debuggerType = DEBUGGER_CLI;
|
opts->debuggerType = DEBUGGER_CLI;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'f':
|
|
||||||
opts->fullscreen = 1;
|
|
||||||
break;
|
|
||||||
#ifdef USE_GDB_STUB
|
#ifdef USE_GDB_STUB
|
||||||
case 'g':
|
case 'g':
|
||||||
if (opts->debuggerType != DEBUGGER_NONE) {
|
if (opts->debuggerType != DEBUGGER_NONE) {
|
||||||
|
@ -76,31 +80,15 @@ int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, c
|
||||||
case 's':
|
case 's':
|
||||||
opts->frameskip = atoi(optarg);
|
opts->frameskip = atoi(optarg);
|
||||||
break;
|
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:
|
default:
|
||||||
|
if (subparser) {
|
||||||
|
if (!subparser->parse(subparser, ch, optarg)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
|
@ -111,11 +99,55 @@ int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, c
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
opts->fd = open(opts->fname, O_RDONLY);
|
opts->fd = open(opts->fname, O_RDONLY);
|
||||||
opts->width *= multiplier;
|
|
||||||
opts->height *= multiplier;
|
|
||||||
return 1;
|
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) {
|
struct ARMDebugger* createDebugger(struct StartupOptions* opts) {
|
||||||
union DebugUnion {
|
union DebugUnion {
|
||||||
struct ARMDebugger d;
|
struct ARMDebugger d;
|
||||||
|
|
|
@ -14,19 +14,6 @@ enum DebuggerType {
|
||||||
DEBUGGER_MAX
|
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 {
|
struct StartupOptions {
|
||||||
int fd;
|
int fd;
|
||||||
const char* fname;
|
const char* fname;
|
||||||
|
@ -35,19 +22,28 @@ struct StartupOptions {
|
||||||
int rewindBufferCapacity;
|
int rewindBufferCapacity;
|
||||||
int rewindBufferInterval;
|
int rewindBufferInterval;
|
||||||
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int fullscreen;
|
|
||||||
|
|
||||||
int perfDuration;
|
|
||||||
|
|
||||||
enum DebuggerType debuggerType;
|
enum DebuggerType debuggerType;
|
||||||
int debugAtStart;
|
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 usage(const char* arg0, const char* extraOptions);
|
||||||
|
|
||||||
|
void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts);
|
||||||
struct ARMDebugger* createDebugger(struct StartupOptions* opts);
|
struct ARMDebugger* createDebugger(struct StartupOptions* opts);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,12 +2,23 @@
|
||||||
#include "gba.h"
|
#include "gba.h"
|
||||||
#include "renderers/video-software.h"
|
#include "renderers/video-software.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/time.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 _GBAPerfRunloop(struct GBAThread* context, int* frames);
|
||||||
static void _GBAPerfShutdown(int signal);
|
static void _GBAPerfShutdown(int signal);
|
||||||
|
static int _parsePerfOpts(struct SubParser* parser, int option, const char* arg);
|
||||||
|
|
||||||
static struct GBAThread* _thread;
|
static struct GBAThread* _thread;
|
||||||
|
|
||||||
|
@ -17,8 +28,16 @@ int main(int argc, char** argv) {
|
||||||
struct GBAVideoSoftwareRenderer renderer;
|
struct GBAVideoSoftwareRenderer renderer;
|
||||||
GBAVideoSoftwareRendererCreate(&renderer);
|
GBAVideoSoftwareRendererCreate(&renderer);
|
||||||
|
|
||||||
|
struct PerfOpts perfOpts = {};
|
||||||
|
struct SubParser subparser = {
|
||||||
|
.usage = PERF_USAGE,
|
||||||
|
.parse = _parsePerfOpts,
|
||||||
|
.extraOptions = PERF_OPTIONS,
|
||||||
|
.opts = &perfOpts
|
||||||
|
};
|
||||||
|
|
||||||
struct StartupOptions opts;
|
struct StartupOptions opts;
|
||||||
if (!parseCommandArgs(&opts, argc, argv, PERF_OPTIONS)) {
|
if (!parseCommandArgs(&opts, argc, argv, &subparser)) {
|
||||||
usage(argv[0], PERF_USAGE);
|
usage(argv[0], PERF_USAGE);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +58,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
GBAThreadStart(&context);
|
GBAThreadStart(&context);
|
||||||
|
|
||||||
int frames = opts.perfDuration;
|
int frames = perfOpts.duration;
|
||||||
time_t start = time(0);
|
time_t start = time(0);
|
||||||
_GBAPerfRunloop(&context, &frames);
|
_GBAPerfRunloop(&context, &frames);
|
||||||
time_t end = time(0);
|
time_t end = time(0);
|
||||||
|
@ -96,3 +115,14 @@ static void _GBAPerfShutdown(int signal) {
|
||||||
_thread->state = THREAD_EXITING;
|
_thread->state = THREAD_EXITING;
|
||||||
pthread_mutex_unlock(&_thread->stateMutex);
|
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);
|
GBAVideoSoftwareRendererCreate(&renderer.d);
|
||||||
|
|
||||||
struct StartupOptions opts;
|
struct StartupOptions opts;
|
||||||
if (!parseCommandArgs(&opts, argc, argv, GRAPHICS_OPTIONS)) {
|
struct SubParser subparser;
|
||||||
usage(argv[0], GRAPHICS_USAGE);
|
struct GraphicsOpts graphicsOpts;
|
||||||
|
initParserForGraphics(&subparser, &graphicsOpts);
|
||||||
|
if (!parseCommandArgs(&opts, argc, argv, &subparser)) {
|
||||||
|
usage(argv[0], subparser.usage);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.viewportWidth = opts.width;
|
renderer.viewportWidth = graphicsOpts.width;
|
||||||
renderer.viewportHeight = opts.height;
|
renderer.viewportHeight = graphicsOpts.height;
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
renderer.events.fullscreen = opts.fullscreen;
|
renderer.events.fullscreen = graphicsOpts.fullscreen;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!_GBASDLInit(&renderer)) {
|
if (!_GBASDLInit(&renderer)) {
|
||||||
|
|
|
@ -49,13 +49,16 @@ int main(int argc, char** argv) {
|
||||||
GBAVideoSoftwareRendererCreate(&renderer.d);
|
GBAVideoSoftwareRendererCreate(&renderer.d);
|
||||||
|
|
||||||
struct StartupOptions opts;
|
struct StartupOptions opts;
|
||||||
if (!parseCommandArgs(&opts, argc, argv, GRAPHICS_OPTIONS)) {
|
struct SubParser subparser;
|
||||||
usage(argv[0], GRAPHICS_USAGE);
|
struct GraphicsOpts graphicsOpts;
|
||||||
|
initParserForGraphics(&subparser, &graphicsOpts);
|
||||||
|
if (!parseCommandArgs(&opts, argc, argv, &subparser)) {
|
||||||
|
usage(argv[0], subparser.usage);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.viewportWidth = opts.width;
|
renderer.viewportWidth = graphicsOpts.width;
|
||||||
renderer.viewportHeight = opts.height;
|
renderer.viewportHeight = graphicsOpts.height;
|
||||||
|
|
||||||
if (!_GBASDLInit(&renderer)) {
|
if (!_GBASDLInit(&renderer)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -75,7 +78,7 @@ int main(int argc, char** argv) {
|
||||||
GBAMapOptionsToContext(&opts, &context);
|
GBAMapOptionsToContext(&opts, &context);
|
||||||
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#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));
|
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);
|
SDL_GetWindowSize(renderer.window, &renderer.viewportWidth, &renderer.viewportHeight);
|
||||||
renderer.events.window = renderer.window;
|
renderer.events.window = renderer.window;
|
||||||
|
@ -100,7 +103,7 @@ int main(int argc, char** argv) {
|
||||||
SDL_Surface* surface = SDL_GetVideoSurface();
|
SDL_Surface* surface = SDL_GetVideoSurface();
|
||||||
SDL_LockSurface(surface);
|
SDL_LockSurface(surface);
|
||||||
|
|
||||||
renderer.ratio = renderer.viewportWidth / VIDEO_HORIZONTAL_PIXELS;
|
renderer.ratio = graphicsOpts.multiplier;
|
||||||
if (renderer.ratio == 1) {
|
if (renderer.ratio == 1) {
|
||||||
renderer.d.outputBuffer = surface->pixels;
|
renderer.d.outputBuffer = surface->pixels;
|
||||||
#ifdef COLOR_16_BIT
|
#ifdef COLOR_16_BIT
|
||||||
|
|
Loading…
Reference in New Issue