Feature: Modernize argument parsing API

This commit is contained in:
Vicki Pfau 2022-04-21 18:42:48 -07:00
parent 770b121b10
commit 4556d4b121
12 changed files with 200 additions and 109 deletions

View File

@ -31,12 +31,20 @@ struct mArguments {
bool showVersion; bool showVersion;
}; };
struct mOption {
const char* name;
bool arg;
char shortEquiv;
};
struct mCoreConfig; struct mCoreConfig;
struct mSubParser { struct mSubParser {
const char* usage; const char* usage;
bool (*parse)(struct mSubParser* parser, int option, const char* arg); bool (*parse)(struct mSubParser* parser, int option, const char* arg);
bool (*parseLong)(struct mSubParser* parser, const char* option, const char* arg);
void (*apply)(struct mSubParser* parser, struct mCoreConfig* config); void (*apply)(struct mSubParser* parser, struct mCoreConfig* config);
const char* extraOptions; const char* extraOptions;
const struct mOption* longOptions;
void* opts; void* opts;
}; };
@ -45,15 +53,14 @@ struct mGraphicsOpts {
bool fullscreen; bool fullscreen;
}; };
bool parseArguments(struct mArguments* args, int argc, char* const* argv, void usage(const char* arg0, const char* prologue, const char* epilogue, const struct mSubParser* subparsers, int nSubparsers);
struct mSubParser* subparser);
void applyArguments(const struct mArguments* args, struct mSubParser* subparser, struct mCoreConfig* config);
void freeArguments(struct mArguments* args);
void usage(const char* arg0, const char* extraOptions);
void version(const char* arg0); void version(const char* arg0);
void initParserForGraphics(struct mSubParser* parser, struct mGraphicsOpts* opts); bool mArgumentsParse(struct mArguments* args, int argc, char* const* argv, struct mSubParser* subparsers, int nSubparsers);
void mArgumentsApply(const struct mArguments* args, struct mSubParser* subparsers, int nSubparsers, struct mCoreConfig* config);
void mArgumentsDeinit(struct mArguments* args);
void mSubParserGraphicsInit(struct mSubParser* parser, struct mGraphicsOpts* opts);
CXX_GUARD_END CXX_GUARD_END

View File

@ -16,16 +16,12 @@
#include <getopt.h> #include <getopt.h>
#endif #endif
#define GRAPHICS_OPTIONS "123456f" #define GRAPHICS_OPTIONS "12345678f"
#define GRAPHICS_USAGE \ #define GRAPHICS_USAGE \
"\nGraphics options:\n" \ "Graphics options:\n" \
" -1 1x viewport\n" \ " -1, -2, -3, -4, -5, -6, -7, -8 Scale viewport by 1-8 times\n" \
" -2 2x viewport\n" \ " -f, --fullscreen Start full-screen\n" \
" -3 3x viewport\n" \ " --scale X Scale viewport by X times"
" -4 4x viewport\n" \
" -5 5x viewport\n" \
" -6 6x viewport\n" \
" -f Start full-screen"
static const struct option _options[] = { static const struct option _options[] = {
{ "bios", required_argument, 0, 'b' }, { "bios", required_argument, 0, 'b' },
@ -45,7 +41,14 @@ static const struct option _options[] = {
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
static const struct mOption _graphicsLongOpts[] = {
{ "fullscreen", false, 'f' },
{ "scale", true, '\0' },
{ 0, 0, 0 }
};
static bool _parseGraphicsArg(struct mSubParser* parser, int option, const char* arg); static bool _parseGraphicsArg(struct mSubParser* parser, int option, const char* arg);
static bool _parseLongGraphicsArg(struct mSubParser* parser, const char* option, const char* arg);
static void _applyGraphicsArgs(struct mSubParser* parser, struct mCoreConfig* config); static void _applyGraphicsArgs(struct mSubParser* parser, struct mCoreConfig* config);
static void _tableInsert(struct Table* table, const char* pair) { static void _tableInsert(struct Table* table, const char* pair) {
@ -65,9 +68,9 @@ static void _tableApply(const char* key, void* value, void* user) {
mCoreConfigSetOverrideValue(config, key, value); mCoreConfigSetOverrideValue(config, key, value);
} }
bool parseArguments(struct mArguments* args, int argc, char* const* argv, struct mSubParser* subparser) { bool mArgumentsParse(struct mArguments* args, int argc, char* const* argv, struct mSubParser* subparsers, int nSubparsers) {
int ch; int ch;
char options[64] = char options[128] =
"b:c:C:hl:p:s:t:" "b:c:C:hl:p:s:t:"
#ifdef USE_EDITLINE #ifdef USE_EDITLINE
"d" "d"
@ -76,23 +79,51 @@ bool parseArguments(struct mArguments* args, int argc, char* const* argv, struct
"g" "g"
#endif #endif
; ;
struct option longOptions[128] = {0};
memcpy(longOptions, _options, sizeof(_options));
memset(args, 0, sizeof(*args)); memset(args, 0, sizeof(*args));
args->frameskip = -1; args->frameskip = -1;
args->logLevel = INT_MIN; args->logLevel = INT_MIN;
HashTableInit(&args->configOverrides, 0, free); HashTableInit(&args->configOverrides, 0, free);
if (subparser && subparser->extraOptions) { int lastLongOpt;
// TODO: modularize options to subparsers
strncat(options, subparser->extraOptions, sizeof(options) - strlen(options) - 1); int i, j;
for (i = 0; _options[i].name; ++i); // Seek to end
lastLongOpt = i;
for (i = 0; i < nSubparsers; ++i) {
if (subparsers[i].extraOptions) {
strncat(options, subparsers[i].extraOptions, sizeof(options) - strlen(options) - 1);
}
if (subparsers[i].longOptions) {
for (j = 0; subparsers[i].longOptions[j].name; ++j) {
longOptions[lastLongOpt].name = subparsers[i].longOptions[j].name;
longOptions[lastLongOpt].has_arg = subparsers[i].longOptions[j].arg ? required_argument : no_argument;
longOptions[lastLongOpt].flag = NULL;
longOptions[lastLongOpt].val = subparsers[i].longOptions[j].shortEquiv;
++lastLongOpt;
}
}
} }
bool ok = false;
int index = 0; int index = 0;
while ((ch = getopt_long(argc, argv, options, _options, &index)) != -1) { while ((ch = getopt_long(argc, argv, options, longOptions, &index)) != -1) {
const struct option* opt = &_options[index]; const struct option* opt = &longOptions[index];
switch (ch) { switch (ch) {
case '\0': case '\0':
if (strcmp(opt->name, "version") == 0) { if (strcmp(opt->name, "version") == 0) {
args->showVersion = true; args->showVersion = true;
} else { } else {
return false; for (i = 0; i < nSubparsers; ++i) {
if (subparsers[i].parseLong) {
ok = subparsers[i].parseLong(&subparsers[i], opt->name, optarg) || ok;
}
}
if (!ok) {
return false;
}
} }
break; break;
case 'b': case 'b':
@ -136,11 +167,14 @@ bool parseArguments(struct mArguments* args, int argc, char* const* argv, struct
args->savestate = strdup(optarg); args->savestate = strdup(optarg);
break; break;
default: default:
if (subparser) { for (i = 0; i < nSubparsers; ++i) {
if (!subparser->parse(subparser, ch, optarg)) { if (subparsers[i].parse) {
return false; ok = subparsers[i].parse(&subparsers[i], ch, optarg) || ok;
} }
} }
if (!ok) {
return false;
}
break; break;
} }
} }
@ -156,7 +190,7 @@ bool parseArguments(struct mArguments* args, int argc, char* const* argv, struct
return true; return true;
} }
void applyArguments(const struct mArguments* args, struct mSubParser* subparser, struct mCoreConfig* config) { void mArgumentsApply(const struct mArguments* args, struct mSubParser* subparsers, int nSubparsers, struct mCoreConfig* config) {
if (args->frameskip >= 0) { if (args->frameskip >= 0) {
mCoreConfigSetOverrideIntValue(config, "frameskip", args->frameskip); mCoreConfigSetOverrideIntValue(config, "frameskip", args->frameskip);
} }
@ -168,12 +202,15 @@ void applyArguments(const struct mArguments* args, struct mSubParser* subparser,
mCoreConfigSetOverrideIntValue(config, "useBios", true); mCoreConfigSetOverrideIntValue(config, "useBios", true);
} }
HashTableEnumerate(&args->configOverrides, _tableApply, config); HashTableEnumerate(&args->configOverrides, _tableApply, config);
if (subparser) { int i;
subparser->apply(subparser, config); for (i = 0; i < nSubparsers; ++i) {
if (subparsers[i].apply) {
subparsers[i].apply(&subparsers[i], config);
}
} }
} }
void freeArguments(struct mArguments* args) { void mArgumentsDeinit(struct mArguments* args) {
free(args->fname); free(args->fname);
args->fname = 0; args->fname = 0;
@ -192,12 +229,14 @@ void freeArguments(struct mArguments* args) {
HashTableDeinit(&args->configOverrides); HashTableDeinit(&args->configOverrides);
} }
void initParserForGraphics(struct mSubParser* parser, struct mGraphicsOpts* opts) { void mSubParserGraphicsInit(struct mSubParser* parser, struct mGraphicsOpts* opts) {
parser->usage = GRAPHICS_USAGE; parser->usage = GRAPHICS_USAGE;
parser->opts = opts; parser->opts = opts;
parser->parse = _parseGraphicsArg; parser->parse = _parseGraphicsArg;
parser->parseLong = _parseLongGraphicsArg;
parser->apply = _applyGraphicsArgs; parser->apply = _applyGraphicsArgs;
parser->extraOptions = GRAPHICS_OPTIONS; parser->extraOptions = GRAPHICS_OPTIONS;
parser->longOptions = _graphicsLongOpts;
opts->multiplier = 0; opts->multiplier = 0;
opts->fullscreen = false; opts->fullscreen = false;
} }
@ -215,6 +254,8 @@ bool _parseGraphicsArg(struct mSubParser* parser, int option, const char* arg) {
case '4': case '4':
case '5': case '5':
case '6': case '6':
case '7':
case '8':
if (graphicsOpts->multiplier) { if (graphicsOpts->multiplier) {
return false; return false;
} }
@ -225,6 +266,18 @@ bool _parseGraphicsArg(struct mSubParser* parser, int option, const char* arg) {
} }
} }
bool _parseLongGraphicsArg(struct mSubParser* parser, const char* option, const char* arg) {
struct mGraphicsOpts* graphicsOpts = parser->opts;
if (strcmp(option, "scale") == 0) {
if (graphicsOpts->multiplier) {
return false;
}
graphicsOpts->multiplier = atoi(arg);
return graphicsOpts->multiplier != 0;
}
return false;
}
void _applyGraphicsArgs(struct mSubParser* parser, struct mCoreConfig* config) { void _applyGraphicsArgs(struct mSubParser* parser, struct mCoreConfig* config) {
struct mGraphicsOpts* graphicsOpts = parser->opts; struct mGraphicsOpts* graphicsOpts = parser->opts;
if (graphicsOpts->fullscreen) { if (graphicsOpts->fullscreen) {
@ -232,25 +285,36 @@ void _applyGraphicsArgs(struct mSubParser* parser, struct mCoreConfig* config) {
} }
} }
void usage(const char* arg0, const char* extraOptions) { void usage(const char* arg0, const char* prologue, const char* epilogue, const struct mSubParser* subparsers, int nSubparsers) {
printf("usage: %s [option ...] file\n", arg0); printf("usage: %s [option ...] file\n", arg0);
puts("\nGeneric options:"); if (prologue) {
puts(" -b, --bios FILE GBA BIOS file to use"); puts(prologue);
puts(" -c, --cheats FILE Apply cheat codes from a file"); }
puts(" -C, --config OPTION=VALUE Override config value"); puts("\nGeneric options:\n"
" -b, --bios FILE GBA BIOS file to use\n"
" -c, --cheats FILE Apply cheat codes from a file\n"
" -C, --config OPTION=VALUE Override config value\n"
#ifdef USE_EDITLINE #ifdef USE_EDITLINE
puts(" -d, --debug Use command-line debugger"); " -d, --debug Use command-line debugger\n"
#endif #endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
puts(" -g, --gdb Start GDB session (default port 2345)"); " -g, --gdb Start GDB session (default port 2345)\n"
#endif #endif
puts(" -l, --log-level N Log level mask"); " -l, --log-level N Log level mask\n"
puts(" -t, --savestate FILE Load savestate when starting"); " -t, --savestate FILE Load savestate when starting\n"
puts(" -p, --patch FILE Apply a specified patch file when running"); " -p, --patch FILE Apply a specified patch file when running\n"
puts(" -s, --frameskip N Skip every N frames"); " -s, --frameskip N Skip every N frames\n"
puts(" --version Print version and exit"); " --version Print version and exit"
if (extraOptions) { );
puts(extraOptions); int i;
for (i = 0; i < nSubparsers; ++i) {
if (subparsers[i].usage) {
puts("");
puts(subparsers[i].usage);
}
}
if (epilogue) {
puts(epilogue);
} }
} }

View File

@ -16,14 +16,14 @@ int main(int argc, char** argv) {
// Arguments from the command line are parsed by the parseArguments function. // Arguments from the command line are parsed by the parseArguments function.
// The NULL here shows that we don't give it any arguments beyond the default ones. // The NULL here shows that we don't give it any arguments beyond the default ones.
struct mArguments args = {}; struct mArguments args = {};
bool parsed = parseArguments(&args, argc, argv, NULL); bool parsed = mArgumentsParse(&args, argc, argv, NULL, 0);
// Parsing can succeed without finding a filename, but we need one. // Parsing can succeed without finding a filename, but we need one.
if (!args.fname) { if (!args.fname) {
parsed = false; parsed = false;
} }
if (!parsed || args.showHelp) { if (!parsed || args.showHelp) {
// If parsing failed, or the user passed --help, show usage. // If parsing failed, or the user passed --help, show usage.
usage(argv[0], NULL); usage(argv[0], NULL, NULL, NULL, 0);
didFail = !parsed; didFail = !parsed;
goto cleanup; goto cleanup;
} }
@ -65,7 +65,7 @@ int main(int argc, char** argv) {
SocketSubsystemDeinit(); SocketSubsystemDeinit();
cleanup: cleanup:
freeArguments(&args); mArgumentsDeinit(&args);
return didFail; return didFail;
} }
@ -114,7 +114,7 @@ bool _mExampleRun(const struct mArguments* args, Socket client) {
// loaded into the config system, as well as manually overriding the // loaded into the config system, as well as manually overriding the
// "idleOptimization" setting to ensure cores that can detect idle loops // "idleOptimization" setting to ensure cores that can detect idle loops
// will attempt the detection. // will attempt the detection.
applyArguments(args, NULL, &core->config); mArgumentsApply(args, NULL, 0, &core->config);
mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "detect"); mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "detect");
// Tell the core to apply the configuration in the associated config object. // Tell the core to apply the configuration in the associated config object.

View File

@ -130,13 +130,22 @@ ConfigController::ConfigController(QObject* parent)
ConfigController::~ConfigController() { ConfigController::~ConfigController() {
mCoreConfigDeinit(&m_config); mCoreConfigDeinit(&m_config);
mCoreConfigFreeOpts(&m_opts); mCoreConfigFreeOpts(&m_opts);
if (m_parsed) {
mArgumentsDeinit(&m_args);
}
} }
bool ConfigController::parseArguments(mArguments* args, int argc, char* argv[], mSubParser* subparser) { bool ConfigController::parseArguments(int argc, char* argv[]) {
if (::parseArguments(args, argc, argv, subparser)) { if (m_parsed) {
return false;
}
mSubParserGraphicsInit(&m_subparsers[0], &m_graphicsOpts);
if (mArgumentsParse(&m_args, argc, argv, m_subparsers.data(), m_subparsers.size())) {
mCoreConfigFreeOpts(&m_opts); mCoreConfigFreeOpts(&m_opts);
applyArguments(args, subparser, &m_config); mArgumentsApply(&m_args, m_subparsers.data(), m_subparsers.size(), &m_config);
mCoreConfigMap(&m_config, &m_opts); mCoreConfigMap(&m_config, &m_opts);
m_parsed = true;
return true; return true;
} }
return false; return false;
@ -299,6 +308,10 @@ void ConfigController::makePortable() {
m_settings = std::move(settings2); m_settings = std::move(settings2);
} }
void ConfigController::usage(const char* arg0) const {
::usage(arg0, nullptr, nullptr, m_subparsers.data(), m_subparsers.size());
}
bool ConfigController::isPortable() { bool ConfigController::isPortable() {
return mCoreConfigIsPortable(); return mCoreConfigIsPortable();
} }

View File

@ -12,6 +12,7 @@
#include <QSettings> #include <QSettings>
#include <QVariant> #include <QVariant>
#include <array>
#include <functional> #include <functional>
#include <memory> #include <memory>
@ -70,7 +71,7 @@ public:
~ConfigController(); ~ConfigController();
const mCoreOptions* options() const { return &m_opts; } const mCoreOptions* options() const { return &m_opts; }
bool parseArguments(mArguments* args, int argc, char* argv[], mSubParser* subparser = nullptr); bool parseArguments(int argc, char* argv[]);
ConfigOption* addOption(const char* key); ConfigOption* addOption(const char* key);
void updateOption(const char* key); void updateOption(const char* key);
@ -91,6 +92,10 @@ public:
const mCoreConfig* config() const { return &m_config; } const mCoreConfig* config() const { return &m_config; }
mCoreConfig* config() { return &m_config; } mCoreConfig* config() { return &m_config; }
const mArguments* args() const { return &m_args; }
const mGraphicsOpts* graphicsOpts() const { return &m_graphicsOpts; }
void usage(const char* arg0) const;
static const QString& configDir(); static const QString& configDir();
static bool isPortable(); static bool isPortable();
@ -110,6 +115,10 @@ private:
mCoreConfig m_config; mCoreConfig m_config;
mCoreOptions m_opts{}; mCoreOptions m_opts{};
mArguments m_args{};
mGraphicsOpts m_graphicsOpts{};
std::array<mSubParser, 1> m_subparsers;
bool m_parsed = false;
QHash<QString, ConfigOption*> m_optionSet; QHash<QString, ConfigOption*> m_optionSet;
std::unique_ptr<QSettings> m_settings; std::unique_ptr<QSettings> m_settings;

View File

@ -179,8 +179,8 @@ Window::~Window() {
#endif #endif
} }
void Window::argumentsPassed(mArguments* args) { void Window::argumentsPassed() {
loadConfig(); const mArguments* args = m_config->args();
if (args->patch) { if (args->patch) {
m_pendingPatch = args->patch; m_pendingPatch = args->patch;
@ -203,9 +203,24 @@ void Window::argumentsPassed(mArguments* args) {
} }
#endif #endif
if (m_config->graphicsOpts()->multiplier) {
m_savedScale = m_config->graphicsOpts()->multiplier;
#if defined(M_CORE_GBA)
QSize size(GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS);
#elif defined(M_CORE_GB)
QSize size(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS);
#endif
resizeFrame(size * m_savedScale);
}
if (args->fname) { if (args->fname) {
setController(m_manager->loadGame(args->fname), args->fname); setController(m_manager->loadGame(args->fname), args->fname);
} }
if (m_config->graphicsOpts()->fullscreen) {
enterFullScreen();
}
} }
void Window::resizeFrame(const QSize& size) { void Window::resizeFrame(const QSize& size) {

View File

@ -24,8 +24,6 @@
#include "LogController.h" #include "LogController.h"
#include "SettingsView.h" #include "SettingsView.h"
struct mArguments;
namespace QGBA { namespace QGBA {
class AudioProcessor; class AudioProcessor;
@ -59,7 +57,7 @@ public:
void setConfig(ConfigController*); void setConfig(ConfigController*);
ConfigController* config() { return m_config; } ConfigController* config() { return m_config; }
void argumentsPassed(mArguments*); void argumentsPassed();
void resizeFrame(const QSize& size); void resizeFrame(const QSize& size);

View File

@ -68,22 +68,18 @@ int main(int argc, char* argv[]) {
QLocale::setDefault(locale); QLocale::setDefault(locale);
} }
mArguments args; if (configController.parseArguments(argc, argv)) {
mGraphicsOpts graphicsOpts; if (configController.args()->showHelp) {
mSubParser subparser; configController.usage(argv[0]);
initParserForGraphics(&subparser, &graphicsOpts);
bool loaded = configController.parseArguments(&args, argc, argv, &subparser);
if (loaded) {
if (args.showHelp) {
usage(argv[0], subparser.usage);
freeArguments(&args);
return 0; return 0;
} }
if (args.showVersion) { if (configController.args()->showVersion) {
version(argv[0]); version(argv[0]);
freeArguments(&args);
return 0; return 0;
} }
} else {
configController.usage(argv[0]);
return 1;
} }
QApplication::setApplicationName(projectName); QApplication::setApplicationName(projectName);
@ -117,19 +113,8 @@ int main(int argc, char* argv[]) {
application.installTranslator(&langTranslator); application.installTranslator(&langTranslator);
Window* w = application.newWindow(); Window* w = application.newWindow();
if (loaded) { w->loadConfig();
w->argumentsPassed(&args); w->argumentsPassed();
} else {
w->loadConfig();
}
freeArguments(&args);
if (graphicsOpts.multiplier) {
w->resizeFrame(QSize(GBA_VIDEO_HORIZONTAL_PIXELS * graphicsOpts.multiplier, GBA_VIDEO_VERTICAL_PIXELS * graphicsOpts.multiplier));
}
if (graphicsOpts.fullscreen) {
w->enterFullScreen();
}
w->show(); w->show();

View File

@ -80,37 +80,37 @@ int main(int argc, char** argv) {
struct mSubParser subparser; struct mSubParser subparser;
initParserForGraphics(&subparser, &graphicsOpts); mSubParserGraphicsInit(&subparser, &graphicsOpts);
bool parsed = parseArguments(&args, argc, argv, &subparser); bool parsed = mArgumentsParse(&args, argc, argv, &subparser, 1);
if (!args.fname && !args.showVersion) { if (!args.fname && !args.showVersion) {
parsed = false; parsed = false;
} }
if (!parsed || args.showHelp) { if (!parsed || args.showHelp) {
usage(argv[0], subparser.usage); usage(argv[0], NULL, NULL, &subparser, 1);
freeArguments(&args); mArgumentsDeinit(&args);
return !parsed; return !parsed;
} }
if (args.showVersion) { if (args.showVersion) {
version(argv[0]); version(argv[0]);
freeArguments(&args); mArgumentsDeinit(&args);
return 0; return 0;
} }
if (SDL_Init(SDL_INIT_VIDEO) < 0) { if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Could not initialize video: %s\n", SDL_GetError()); printf("Could not initialize video: %s\n", SDL_GetError());
freeArguments(&args); mArgumentsDeinit(&args);
return 1; return 1;
} }
renderer.core = mCoreFind(args.fname); renderer.core = mCoreFind(args.fname);
if (!renderer.core) { if (!renderer.core) {
printf("Could not run game. Are you sure the file exists and is a compatible game?\n"); printf("Could not run game. Are you sure the file exists and is a compatible game?\n");
freeArguments(&args); mArgumentsDeinit(&args);
return 1; return 1;
} }
if (!renderer.core->init(renderer.core)) { if (!renderer.core->init(renderer.core)) {
freeArguments(&args); mArgumentsDeinit(&args);
return 1; return 1;
} }
@ -134,7 +134,7 @@ int main(int argc, char** argv) {
mInputMapInit(&renderer.core->inputMap, &GBAInputInfo); mInputMapInit(&renderer.core->inputMap, &GBAInputInfo);
mCoreInitConfig(renderer.core, PORT); mCoreInitConfig(renderer.core, PORT);
applyArguments(&args, &subparser, &renderer.core->config); mArgumentsApply(&args, &subparser, 1, &renderer.core->config);
mCoreConfigLoadDefaults(&renderer.core->config, &opts); mCoreConfigLoadDefaults(&renderer.core->config, &opts);
mCoreLoadConfig(renderer.core); mCoreLoadConfig(renderer.core);
@ -168,7 +168,7 @@ int main(int argc, char** argv) {
} }
if (!renderer.init(&renderer)) { if (!renderer.init(&renderer)) {
freeArguments(&args); mArgumentsDeinit(&args);
mCoreConfigDeinit(&renderer.core->config); mCoreConfigDeinit(&renderer.core->config);
renderer.core->deinit(renderer.core); renderer.core->deinit(renderer.core);
return 1; return 1;
@ -199,7 +199,7 @@ int main(int argc, char** argv) {
mSDLDeinit(&renderer); mSDLDeinit(&renderer);
freeArguments(&args); mArgumentsDeinit(&args);
mCoreConfigFreeOpts(&opts); mCoreConfigFreeOpts(&opts);
mCoreConfigDeinit(&renderer.core->config); mCoreConfigDeinit(&renderer.core->config);
renderer.core->deinit(renderer.core); renderer.core->deinit(renderer.core);

View File

@ -22,7 +22,7 @@
#define FUZZ_OPTIONS "F:NO:S:V:" #define FUZZ_OPTIONS "F:NO:S:V:"
#define FUZZ_USAGE \ #define FUZZ_USAGE \
"\nAdditional options:\n" \ "Additional options:\n" \
" -F FRAMES Run for the specified number of FRAMES before exiting\n" \ " -F FRAMES Run for the specified number of FRAMES before exiting\n" \
" -N Disable video rendering entirely\n" \ " -N Disable video rendering entirely\n" \
" -O OFFSET Offset to apply savestate overlay\n" \ " -O OFFSET Offset to apply savestate overlay\n" \
@ -53,12 +53,12 @@ int main(int argc, char** argv) {
}; };
struct mArguments args; struct mArguments args;
bool parsed = parseArguments(&args, argc, argv, &subparser); bool parsed = mArgumentsParse(&args, argc, argv, &subparser, 1);
if (!args.fname) { if (!args.fname) {
parsed = false; parsed = false;
} }
if (!parsed || args.showHelp) { if (!parsed || args.showHelp) {
usage(argv[0], FUZZ_USAGE); usage(argv[0], NULL, NULL, &subparser, 1);
return !parsed; return !parsed;
} }
if (args.showVersion) { if (args.showVersion) {
@ -71,7 +71,7 @@ int main(int argc, char** argv) {
} }
core->init(core); core->init(core);
mCoreInitConfig(core, "fuzz"); mCoreInitConfig(core, "fuzz");
applyArguments(&args, NULL, &core->config); mArgumentsApply(&args, NULL, 0, &core->config);
mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "remove"); mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "remove");
@ -161,7 +161,7 @@ int main(int argc, char** argv) {
} }
loadError: loadError:
freeArguments(&args); mArgumentsDeinit(&args);
if (outputBuffer) { if (outputBuffer) {
free(outputBuffer); free(outputBuffer);
} }

View File

@ -44,7 +44,7 @@ size_t romBufferSize;
#define PERF_OPTIONS "DF:L:NPS:T" #define PERF_OPTIONS "DF:L:NPS:T"
#define PERF_USAGE \ #define PERF_USAGE \
"\nBenchmark options:\n" \ "Benchmark options:\n" \
" -F FRAMES Run for the specified number of FRAMES before exiting\n" \ " -F FRAMES Run for the specified number of FRAMES before exiting\n" \
" -N Disable video rendering entirely\n" \ " -N Disable video rendering entirely\n" \
" -T Use threaded video rendering\n" \ " -T Use threaded video rendering\n" \
@ -131,12 +131,12 @@ int main(int argc, char** argv) {
}; };
struct mArguments args = {}; struct mArguments args = {};
bool parsed = parseArguments(&args, argc, argv, &subparser); bool parsed = mArgumentsParse(&args, argc, argv, &subparser, 1);
if (!args.fname && !perfOpts.server) { if (!args.fname && !perfOpts.server) {
parsed = false; parsed = false;
} }
if (!parsed || args.showHelp) { if (!parsed || args.showHelp) {
usage(argv[0], PERF_USAGE); usage(argv[0], NULL, NULL, &subparser, 1);
didFail = !parsed; didFail = !parsed;
goto cleanup; goto cleanup;
} }
@ -171,7 +171,7 @@ int main(int argc, char** argv) {
_savestate->close(_savestate); _savestate->close(_savestate);
} }
cleanup: cleanup:
freeArguments(&args); mArgumentsDeinit(&args);
#ifdef __3DS__ #ifdef __3DS__
gfxExit(); gfxExit();
@ -217,7 +217,7 @@ bool _mPerfRunCore(const char* fname, const struct mArguments* args, const struc
mCoreConfigMap(&core->config, &opts); mCoreConfigMap(&core->config, &opts);
opts.audioSync = false; opts.audioSync = false;
opts.videoSync = false; opts.videoSync = false;
applyArguments(args, NULL, &core->config); mArgumentsApply(args, NULL, 0, &core->config);
mCoreConfigLoadDefaults(&core->config, &opts); mCoreConfigLoadDefaults(&core->config, &opts);
mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "detect"); mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "detect");
mCoreLoadConfig(core); mCoreLoadConfig(core);

View File

@ -24,7 +24,7 @@
#define ROM_TEST_OPTIONS "S:R:" #define ROM_TEST_OPTIONS "S:R:"
#define ROM_TEST_USAGE \ #define ROM_TEST_USAGE \
"\nAdditional options:\n" \ "Additional options:\n" \
" -S SWI Run until specified SWI call before exiting\n" \ " -S SWI Run until specified SWI call before exiting\n" \
" -R REGISTER General purpose register to return as exit code\n" \ " -R REGISTER General purpose register to return as exit code\n" \
@ -81,12 +81,12 @@ int main(int argc, char * argv[]) {
}; };
struct mArguments args; struct mArguments args;
bool parsed = parseArguments(&args, argc, argv, &subparser); bool parsed = mArgumentsParse(&args, argc, argv, &subparser, 1);
if (!args.fname) { if (!args.fname) {
parsed = false; parsed = false;
} }
if (!parsed || args.showHelp) { if (!parsed || args.showHelp) {
usage(argv[0], ROM_TEST_USAGE); usage(argv[0], NULL, NULL, &subparser, 1);
return !parsed; return !parsed;
} }
if (args.showVersion) { if (args.showVersion) {
@ -99,7 +99,7 @@ int main(int argc, char * argv[]) {
} }
core->init(core); core->init(core);
mCoreInitConfig(core, "romTest"); mCoreInitConfig(core, "romTest");
applyArguments(&args, NULL, &core->config); mArgumentsApply(&args, NULL, 0, &core->config);
mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "remove"); mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "remove");
@ -184,7 +184,7 @@ int main(int argc, char * argv[]) {
cleanExit = true; cleanExit = true;
loadError: loadError:
freeArguments(&args); mArgumentsDeinit(&args);
mCoreConfigDeinit(&core->config); mCoreConfigDeinit(&core->config);
core->deinit(core); core->deinit(core);