Skip to content

Commit

Permalink
Add a notification system to better communicate the result of complex…
Browse files Browse the repository at this point in the history
… operations.
  • Loading branch information
Arignir committed Dec 13, 2023
1 parent 8dc68bd commit bd55c95
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 154 deletions.
16 changes: 16 additions & 0 deletions include/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ enum bind_actions {
extern char const * const binds_pretty_name[];
extern char const * const binds_slug[];

enum ui_notification_kind {
UI_NOTIFICATION_INFO,
UI_NOTIFICATION_SUCCESS,
UI_NOTIFICATION_ERROR,
};

struct ui_notification {
enum ui_notification_kind kind;
char *msg;
uint64_t timeout;
uint64_t fade_time_start;
struct ui_notification *next;
};

struct app {
atomic_bool run;

Expand Down Expand Up @@ -272,6 +286,8 @@ struct app {
SDL_Keycode *keyboard_target;
SDL_GameControllerButton *controller_target;
} keybindings_editor;

struct ui_notification *notifications;
} ui;

struct {
Expand Down
13 changes: 6 additions & 7 deletions include/gui/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
#pragma once

#include "hades.h"

struct app;
#include "app.h"

#define GLSL(src) "#version 330 core\n" #src

Expand Down Expand Up @@ -42,16 +41,16 @@ extern char const *SHADER_VERTEX_COMMON;
/* gui/windows/keybinds.c */
void gui_win_keybinds_editor(struct app *app);

/* gui/windows/error.c */
void gui_new_error(struct app *app, char *msg);
void gui_win_error(struct app *app);

/* gui/windows.c */
/* gui/windows/game.c */
void gui_win_game(struct app *app);

/* gui/windows/menubar.c */
void gui_win_menubar(struct app *app);

/* gui/windows/notif.c */
void gui_new_notification(struct app *app, enum ui_notification_kind, char const *msg, ...);
void gui_win_notifications(struct app *app);

/* config.c */
void gui_config_load(struct app *app);
void gui_config_save(struct app *app);
Expand Down
129 changes: 62 additions & 67 deletions source/common/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,24 +71,20 @@ app_game_process_notif(
goto qsave_err;
}

logln(
HS_INFO,
"State saved to %s%s%s",
g_light_magenta,
path,
g_reset
gui_new_notification(
app,
UI_NOTIFICATION_SUCCESS,
"Game state saved."
);

goto qsave_finally;

qsave_err:
logln(
HS_INFO,
"%sError: failed to save state to %s: %s%s",
g_light_red,
path,
strerror(errno),
g_reset
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to save game state: %s.",
strerror(errno)
);

qsave_finally:
Expand All @@ -103,18 +99,12 @@ app_game_process_notif(
break;
};
case NOTIFICATION_QUICKLOAD: {
char const *path;

hs_assert(app->emulation.quickload_request.enabled);

path = app->file.qsaves[app->emulation.quicksave_request.idx].path;

logln(
HS_INFO,
"State loaded from %s%s%s",
g_light_magenta,
path,
g_reset
gui_new_notification(
app,
UI_NOTIFICATION_SUCCESS,
"Game state loaded."
);

free(app->emulation.quickload_request.data);
Expand Down Expand Up @@ -211,31 +201,35 @@ app_game_configure_bios(
) {
FILE *file;
void *data;
char *error_msg;

if (!app->file.bios_path) {
error_msg = hs_format(
"no BIOS found.\n\nPlease download and select a valid Nintendo GBA Bios using \"File\" -> \"Open BIOS\"."
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"No BIOS found.\nPlease download and select a valid Nintendo GBA Bios using \"File\" -> \"Open BIOS\"."
);
gui_new_error(app, error_msg);
return (true);
}

file = hs_fopen(app->file.bios_path, "rb");
if (!file) {
error_msg = hs_format(
"failed to open %s: %s.",
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to open %s: %s.",
app->file.bios_path,
strerror(errno)
);
gui_new_error(app, error_msg);
return (true);
}

fseek(file, 0, SEEK_END);
if (ftell(file) != 0x4000) {
error_msg = strdup("the BIOS is invalid.");
gui_new_error(app, error_msg);
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"The BIOS is invalid."
);
return (true);
}

Expand All @@ -245,12 +239,13 @@ app_game_configure_bios(
hs_assert(data);

if (fread(data, 1, BIOS_SIZE, file) != BIOS_SIZE) {
error_msg = hs_format(
"failed to read %s: %s.",
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to read %s: %s.",
app->file.bios_path,
strerror(errno)
);
gui_new_error(app, error_msg);
free(data);
return (true);
}
Expand All @@ -270,24 +265,27 @@ app_game_configure_rom(
FILE *file;
size_t file_len;
void *data;
char *error_msg;

file = hs_fopen(rom_path, "rb");
if (!file) {
error_msg = hs_format(
"failed to open %s: %s.",
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to open %s: %s.",
rom_path,
strerror(errno)
);
gui_new_error(app, error_msg);
return (true);
}

fseek(file, 0, SEEK_END);
file_len = ftell(file);
if (file_len > CART_SIZE || file_len < 192) {
error_msg = strdup("the ROM is invalid.");
gui_new_error(app, error_msg);
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"The ROM is invalid."
);
return (true);
}

Expand All @@ -297,12 +295,13 @@ app_game_configure_rom(
hs_assert(data);

if (fread(data, 1, file_len, file) != file_len) {
error_msg = hs_format(
"failed to read %s: %s.",
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to read %s: %s.",
rom_path,
strerror(errno)
);
gui_new_error(app, error_msg);
free(data);
return (true);
}
Expand All @@ -320,7 +319,6 @@ app_game_configure_backup(
char const *backup_path
) {
size_t file_len;
char *error_msg;

app->emulation.backup_file = hs_fopen(backup_path, "rb+");

Expand Down Expand Up @@ -351,12 +349,13 @@ app_game_configure_backup(
app->emulation.backup_file = hs_fopen(backup_path, "wb+");

if (!app->emulation.backup_file) {
error_msg = hs_format(
"failed to create %s: %s.",
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to create %s: %s.",
backup_path,
strerror(errno)
);
gui_new_error(app, error_msg);
return (true);
}
}
Expand Down Expand Up @@ -687,21 +686,18 @@ app_game_screenshot(
pthread_mutex_unlock(&app->emulation.gba->shared_data.framebuffer.lock);

if (out) {
logln(
HS_INFO,
"Screenshot saved in %s%s%s.",
g_light_green,
filename,
g_reset
gui_new_notification(
app,
UI_NOTIFICATION_SUCCESS,
"Screenshot saved in %s.",
filename
);
} else {
logln(
HS_ERROR,
"Failed to save screenshot in %s%s%s.%s",
g_light_green,
filename,
g_light_red,
g_reset
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to save screenshot in %s.",
filename
);
}
}
Expand Down Expand Up @@ -775,13 +771,12 @@ app_game_quickload(
goto finally;

err:
logln(
HS_INFO,
"%sError: failed to load state from %s: %s%s",
g_light_red,
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to load state from %s: %s",
path,
strerror(errno),
g_reset
strerror(errno)
);

free(data);
Expand Down
2 changes: 1 addition & 1 deletion source/gui/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ libgui = static_library(
'sdl/video.c',
'shaders/frag-color-correction.c',
'shaders/vertex-common.c',
'windows/error.c',
'windows/game.c',
'windows/keybinds.c',
'windows/menubar.c',
'windows/notif.c',
dependencies: [
dependency('threads', required: true, static: get_option('static_executable')),
],
Expand Down
2 changes: 1 addition & 1 deletion source/gui/sdl/video.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ gui_sdl_video_render_frame(

gui_win_keybinds_editor(app);

gui_win_error(app);
gui_win_notifications(app);

/* Render the imGui frame */
igRender();
Expand Down
Loading

0 comments on commit bd55c95

Please sign in to comment.