Skip to content

Commit

Permalink
Add a --config and --without-gui option to Hades.
Browse files Browse the repository at this point in the history
  • Loading branch information
Arignir committed Dec 18, 2023
1 parent ca29276 commit 485775a
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 207 deletions.
17 changes: 11 additions & 6 deletions include/app/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ struct app {
struct args {
char const *rom_path;
char const *bios_path;
char const *config_path;
bool with_gui;
} args;

struct {
Expand Down Expand Up @@ -361,6 +363,15 @@ void app_win_menubar(struct app *app);
void app_new_notification(struct app *app, enum ui_notification_kind, char const *msg, ...);
void app_win_notifications(struct app *app);

/* args.c */
void app_args_parse(struct app *app, int argc, char * const argv[]);

/* bindings.c */
void app_bindings_setup_default(struct app *app);
void app_bindings_keyboard_clear(struct app *app, SDL_KeyCode key);
void app_bindings_controller_clear(struct app *app, SDL_GameControllerButton btn);
void app_bindings_handle(struct app *app, enum bind_actions bind, bool pressed);

/* config.c */
void app_config_load(struct app *app);
void app_config_save(struct app *app);
Expand Down Expand Up @@ -392,9 +403,3 @@ void app_emulator_set_breakpoints_list(struct app *app, struct breakpoint *break
void app_emulator_set_watchpoints_list(struct app *app, struct watchpoint *watchpoints, size_t len);

#endif

/* bindings.c */
void app_bindings_setup_default(struct app *app);
void app_bindings_keyboard_clear(struct app *app, SDL_KeyCode key);
void app_bindings_controller_clear(struct app *app, SDL_GameControllerButton btn);
void app_bindings_handle(struct app *app, enum bind_actions bind, bool pressed);
198 changes: 198 additions & 0 deletions source/app/args.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/******************************************************************************\
**
** This file is part of the Hades GBA Emulator, and is made available under
** the terms of the GNU General Public License version 2.
**
** Copyright (C) 2021-2023 - The Hades Authors
**
\******************************************************************************/

#include <getopt.h>
#include <stdio.h>
#include "hades.h"
#include "app/app.h"
#include "compat.h"

/*
** Print the program's usage.
*/
static
void
print_usage(
FILE *file,
char const *name
) {
fprintf(
file,
"Usage: %s [OPTION]... ROM\n"
"\n"
"Options:\n"
" -b, --bios=PATH Path pointing to the bios dump (default: \"bios.bin\")\n"
" -c, --config=PATH Path pointing to the configuration file (default: \"config.json\")\n"
" --color=[always|never|auto] Adjust color settings (default: auto)\n"
#ifdef WITH_DEBUGGER
" --without-gui Disable any gui\n"
#endif
"\n"
" -h, --help Print this help and exit\n"
" -v, --version Print the version information and exit\n"
"",
name
);
}

/*
** Parse the given command line arguments.
*/
void
app_args_parse(
struct app *app,
int argc,
char * const argv[]
) {
char const *name;
uint32_t color;

color = 0;
name = argv[0];
while (true) {
int c;
int option_index;

enum cli_options {
CLI_HELP = 0,
CLI_VERSION,
CLI_BIOS,
CLI_CONFIG,
CLI_COLOR,
CLI_WITHOUT_GUI,
};

static struct option long_options[] = {
[CLI_HELP] = { "help", no_argument, 0, 0 },
[CLI_VERSION] = { "version", no_argument, 0, 0 },
[CLI_BIOS] = { "bios", required_argument, 0, 0 },
[CLI_CONFIG] = { "config", required_argument, 0, 0 },
[CLI_COLOR] = { "color", optional_argument, 0, 0 },
#ifdef WITH_DEBUGGER
[CLI_WITHOUT_GUI] = { "without-gui", no_argument, 0, 0 },
#endif
{ 0, 0, 0, 0 }
};

c = getopt_long(
argc,
argv,
"hvb:c:",
long_options,
&option_index
);

if (c == -1) {
break;
}

switch (c) {
case 0: {
switch (option_index) {
case CLI_HELP: { // --help
print_usage(stdout, name);
exit(EXIT_SUCCESS);
break;
};
case CLI_VERSION: { // --version
printf("Hades v" HADES_VERSION "\n");
exit(EXIT_SUCCESS);
break;
};
case CLI_BIOS: { // --bios
app->args.bios_path = optarg;
break;
};
case CLI_CONFIG: { // --config
app->args.config_path = optarg;
break;
};
case CLI_COLOR: { // --color
if (optarg) {
if (!strcmp(optarg, "auto")) {
color = 0;
break;
} else if (!strcmp(optarg, "never")) {
color = 1;
break;
} else if (!strcmp(optarg, "always")) {
color = 2;
break;
} else {
print_usage(stderr, name);
exit(EXIT_FAILURE);
}
} else {
color = 0;
}
break;
};
case CLI_WITHOUT_GUI: {
app->args.with_gui = false;
break;
};
default: {
print_usage(stderr, name);
exit(EXIT_FAILURE);
break;
};
}
break;
};
case 'b': {
app->args.bios_path = optarg;
break;
};
case 'c': {
app->args.config_path = optarg;
break;
};
case 'h': {
print_usage(stdout, name);
exit(EXIT_SUCCESS);
break;
};
case 'v': {
printf("Hades v" HADES_VERSION "\n");
exit(EXIT_SUCCESS);
break;
};
default: {
print_usage(stderr, name);
exit(EXIT_FAILURE);
break;
};
}
}

switch (argc - optind) {
case 0: {
break;
};
case 1: {
app->args.rom_path = argv[optind];
break;
};
default: {
print_usage(stderr, name);
exit(EXIT_FAILURE);
};
}

switch (color) {
case 0:
if (!hs_isatty(1)) {
disable_colors();
}
break;
case 1:
disable_colors();
break;
}
}
20 changes: 12 additions & 8 deletions source/app/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,22 @@ void
app_config_load(
struct app *app
) {
char const *path;
char data[4096];
FILE *config_file;
size_t data_len;

config_file = hs_fopen(app->file.config_path, "r");
path = app->args.config_path ?: app->file.config_path;
config_file = hs_fopen(path, "r");
if (!config_file) {
logln(HS_ERROR, "Failed to open \"%s\": %s", app->file.config_path, strerror(errno));
logln(HS_ERROR, "Failed to open \"%s\": %s", path, strerror(errno));
return ;
}

data_len = fread(data, 1, sizeof(data) - 1, config_file);

if (data_len == 0 && ferror(config_file)) {
logln(HS_ERROR, "Failed to read \"%s\": %s", app->file.config_path, strerror(errno));
logln(HS_ERROR, "Failed to read \"%s\": %s", path, strerror(errno));
goto end;
}

Expand Down Expand Up @@ -179,6 +181,7 @@ void
app_config_save(
struct app *app
) {
char const *path;
FILE *config_file;
int out;
char *data;
Expand All @@ -189,9 +192,10 @@ app_config_save(
data = NULL;
pretty_data = NULL;

config_file = hs_fopen(app->file.config_path, "w");
path = app->args.config_path ?: app->file.config_path;
config_file = hs_fopen(path, "w");
if (!config_file) {
logln(HS_ERROR, "Failed to open \"%s\": %s", app->file.config_path, strerror(errno));
logln(HS_ERROR, "Failed to open \"%s\": %s", path, strerror(errno));
return ;
}

Expand Down Expand Up @@ -264,7 +268,7 @@ app_config_save(
);

if (!data) {
logln(HS_ERROR, "Failed to write the configuration to \"%s\": the formatted JSON is invalid.", app->file.config_path);
logln(HS_ERROR, "Failed to write the configuration to \"%s\": the formatted JSON is invalid.", path);
goto end;
}

Expand Down Expand Up @@ -324,12 +328,12 @@ app_config_save(
out = mjson_pretty(data, strlen(data), " ", mjson_print_dynamic_buf, &pretty_data);

if (out < 0) {
logln(HS_ERROR, "Failed to write the configuration to \"%s\": the formatted JSON is invalid.", app->file.config_path);
logln(HS_ERROR, "Failed to write the configuration to \"%s\": the formatted JSON is invalid.", path);
goto end;
}

if (fwrite(pretty_data, strlen(pretty_data), 1, config_file) != 1) {
logln(HS_ERROR, "Failed to write the configuration to \"%s\": %s.", app->file.config_path, strerror(errno));
logln(HS_ERROR, "Failed to write the configuration to \"%s\": %s.", path, strerror(errno));
}

end:
Expand Down
Loading

0 comments on commit 485775a

Please sign in to comment.