Basic Last Game and Favorties

Moved the Load last game and favorites with menu into the branch
This commit is contained in:
Ross Gouldthorpe 2024-11-30 21:24:05 +00:00
parent 058c41b8e0
commit 16bbd0c3b8
15 changed files with 532 additions and 7 deletions

View File

@ -49,6 +49,7 @@ SRCS = \
menu/path.c \
menu/png_decoder.c \
menu/rom_info.c \
menu/rom_history.c \
menu/settings.c \
menu/sound.c \
menu/ui_components/background.c \
@ -62,6 +63,7 @@ SRCS = \
menu/views/error.c \
menu/views/fault.c \
menu/views/file_info.c \
menu/views/favorite.c \
menu/views/image_viewer.c \
menu/views/text_viewer.c \
menu/views/load_disk.c \

View File

@ -22,6 +22,8 @@ static void actions_clear (menu_t *menu) {
menu->actions.options = false;
menu->actions.settings = false;
menu->actions.lz_context = false;
menu->actions.favorite = false;
menu->actions.load_last = false;
}
static void actions_update_direction (menu_t *menu) {
@ -109,6 +111,10 @@ static void actions_update_buttons (menu_t *menu) {
menu->actions.settings = true;
} else if (pressed.l || pressed.z) {
menu->actions.lz_context = true;
} else if (pressed.c_left) {
menu->actions.load_last = true;
} else if (pressed.c_right) {
menu->actions.favorite = true;
}
}

View File

@ -23,6 +23,7 @@
#define MENU_DIRECTORY "/menu"
#define MENU_SETTINGS_FILE "config.ini"
#define MENU_CUSTOM_FONT_FILE "custom.font64"
#define MENU_HISTORY_FILE "history.ini"
#define MENU_CACHE_DIRECTORY "cache"
#define BACKGROUND_CACHE_FILE "background.data"
@ -70,6 +71,13 @@ static void menu_init (boot_params_t *boot_params) {
settings_load(&menu->settings);
path_pop(path);
path_push(path, MENU_HISTORY_FILE);
history_init(path_get(path));
history_load(&menu->history);
menu->load.load_last = false;
menu->load.load_favorite = -1;
path_pop(path);
resolution_t resolution = {
.width = 640,
.height = 480,
@ -150,6 +158,8 @@ static view_t menu_views[] = {
{ MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display },
{ MENU_MODE_ERROR, view_error_init, view_error_display },
{ MENU_MODE_FAULT, view_fault_init, view_fault_display },
{ MENU_MODE_FAVORITE, view_favorite_init, view_favorite_display },
{}
};
static view_t *menu_get_view (menu_mode_t id) {

View File

@ -16,6 +16,7 @@
#include "path.h"
#include "rom_info.h"
#include "settings.h"
#include "rom_history.h"
/** @brief Menu mode enumeration */
@ -38,6 +39,7 @@ typedef enum {
MENU_MODE_ERROR,
MENU_MODE_FAULT,
MENU_MODE_BOOT,
MENU_MODE_FAVORITE
} menu_mode_t;
/** @brief File entry type enumeration */
@ -67,6 +69,7 @@ typedef struct {
const char *storage_prefix;
settings_t settings;
history_t history;
boot_params_t *boot_params;
char *error_message;
@ -86,6 +89,8 @@ typedef struct {
bool options;
bool settings;
bool lz_context;
bool favorite;
bool load_last;
} actions;
struct {
@ -103,6 +108,8 @@ typedef struct {
rom_info_t rom_info;
path_t *disk_path;
disk_info_t disk_info;
bool load_last;
int load_favorite;
} load;
struct {

View File

@ -19,7 +19,7 @@ static void path_resize (path_t *path, size_t min_length) {
assert(path->buffer != NULL);
}
static path_t *path_create (const char *string) {
path_t *path_create (const char *string) {
if (string == NULL) {
string = "";
}
@ -141,3 +141,12 @@ void path_ext_replace (path_t *path, char *ext) {
path_append(path, ".");
path_append(path, ext);
}
bool path_has_value(path_t *path) {
if(path != NULL) {
if(strlen(path->buffer) > 0) {
return true;
}
}
return false;
}

View File

@ -19,7 +19,7 @@ typedef struct {
size_t capacity;
} path_t;
path_t *path_create (const char *string);
path_t *path_init (const char *prefix, char *string);
void path_free (path_t *path);
path_t *path_clone (path_t *string);
@ -33,6 +33,6 @@ void path_push_subdir (path_t *path, char *string);
char *path_ext_get (path_t *path);
void path_ext_remove (path_t *path);
void path_ext_replace (path_t *path, char *ext);
bool path_has_value(path_t *path);
#endif

233
src/menu/rom_history.c Normal file
View File

@ -0,0 +1,233 @@
#include <libdragon.h>
#include <mini.c/src/mini.h>
#include "rom_history.h"
#include "utils/fs.h"
#include "path.h"
#define EMULATOR_TEST true
static char *history_path = NULL;
static path_t* empty_path = NULL;
static history_t init;
/** @brief Init history path */
void history_init (char *path) {
if (history_path) {
free(history_path);
}
history_path = strdup(path);
empty_path = path_create("");
}
/** @brief The history to load */
void history_load (history_t *history) {
if (!file_exists(history_path)) {
history_save(&init);
}
mini_t *ini = mini_try_load(history_path);
history->last_rom = path_create(mini_get_string(ini, "history", "last_rom", ""));
history->last_disk = path_create(mini_get_string(ini, "history", "last_disk", ""));
char buffer[1024];
for(int i=0;i<FAVORITES_COUNT;i++) {
#if EMULATOR_TEST
sprintf(buffer, "test:\\somepaths\\blah\\rom - %d.n64", i);
history->favorites_rom[i] = path_create(buffer);
#else
sprintf(buffer,"%dfavorite_rom", i);
history->favorites_rom[i] = path_create(mini_get_string(ini, "favorite", buffer, ""));
#endif
}
for(int i=0;i<FAVORITES_COUNT;i++) {
#if EMULATOR_TEST
sprintf(buffer, "test:\\aother\\foo\\disk - %d.dd", i);
history->favorites_disk[i] = path_create(buffer);
#else
sprintf(buffer,"%dfavorite_disk", i);
history->favorites_disk[i] = path_create(mini_get_string(ini, "favorite", buffer, ""));
#endif
}
mini_free(ini);
}
/** @brief The history to save */
void history_save (history_t *history)
{
mini_t *ini = mini_create(history_path);
mini_set_string(ini, "history", "last_rom", history->last_rom != NULL ? path_get(history->last_rom) : "");
mini_set_string(ini, "history", "last_disk", history->last_disk != NULL ? path_get(history->last_disk) : "");
char buf[20];
for(int i=0;i<FAVORITES_COUNT;i++) {
sprintf(buf,"%dfavorite_rom", i);
path_t* path = history->favorites_rom[i];
mini_set_string(ini, "favorite", buf, path != NULL ? path_get(path) : "");
}
for(int i=0;i<FAVORITES_COUNT;i++) {
sprintf(buf,"%dfavorite_disk", i);
path_t* path = history->favorites_disk[i];
mini_set_string(ini, "favorite", buf, path != NULL ? path_get(path) : "");
}
mini_save(ini, MINI_FLAGS_SKIP_EMPTY_GROUPS);
mini_free(ini);
}
static void history_last_rom_update(history_t *history, path_t* path) {
if(history->last_rom != NULL) {
path_free(history->last_rom);
}
if(path != NULL) {
history->last_rom = path_clone(path);
} else {
history->last_rom = path_create("");
}
}
static void history_last_disk_update(history_t *history, path_t* path) {
if(history->last_disk != NULL) {
path_free(history->last_disk);
}
if(path != NULL) {
history->last_disk = path_clone(path);
} else {
history->last_disk = path_create("");
}
}
void history_last_rom_set(history_t *history, path_t* disk_path, path_t* rom_path)
{
history_last_rom_update(history, rom_path);
history_last_disk_update(history, disk_path);
history_save(history);
}
static void history_favorite_insert(history_t *history, int location, path_t* rom, path_t* disk) {
if(history->favorites_rom[location]) {
path_free(history->favorites_rom[location]);
}
if(history->favorites_disk[location]) {
path_free(history->favorites_disk[location]);
}
history->favorites_rom[location] = rom != NULL ? path_clone(rom) : path_create("");
history->favorites_disk[location] = rom != NULL ? path_clone(disk) : path_create("");
}
static void history_favorite_replace(history_t *history, int toReplace, path_t* rom, path_t* disk) {
if(history->favorites_rom[toReplace]) {
path_free(history->favorites_rom[toReplace]);
history->favorites_rom[toReplace] = NULL;
}
if(rom != NULL) {
history->favorites_rom[toReplace] = path_clone(rom);
}
if(history->favorites_disk[toReplace]) {
path_free(history->favorites_disk[toReplace]);
history->favorites_disk[toReplace] = NULL;
}
if(disk != NULL) {
history->favorites_disk[toReplace] = path_clone(disk);
}
}
static void history_favorite_rotate(history_t *history)
{
for(int i=1;i<FAVORITES_COUNT-1;i++) {
int previous = i-1;
history_favorite_replace(history, previous, history->favorites_rom[i], history->favorites_disk[i]);
}
history_favorite_replace(history, FAVORITES_COUNT -1, NULL, NULL);
}
static bool history_favorite_check_match(path_t* left, path_t* right) {
bool matches = false;
if(left == NULL && right == NULL) {
matches = true;
} else {
if(left != NULL && right != NULL) {
matches = (strcmp(path_get(left), path_get(right)) == 0);
}
}
return matches;
}
static bool history_favorite_exists(history_t *history, path_t* rom, path_t* disk) {
for(int i=0;i<FAVORITES_COUNT;i++) {
bool romMatch = history_favorite_check_match(history->favorites_rom[i], rom);
bool diskMatch = history_favorite_check_match(history->favorites_disk[i], disk);
if(romMatch && diskMatch) {
return true;
}
}
return false;
}
void history_favorite_add(history_t *history, path_t* rom, path_t* disk) {
// if the game is already in the favorite list then don't add again
if(rom == NULL) {
rom = empty_path;
}
if(disk == NULL) {
disk = empty_path;
}
if(history_favorite_exists(history, rom, disk)) {
return;
}
// look for a free space in the list
int place = -1;
for(int i=0;i < FAVORITES_COUNT;i++) {
if(!(path_has_value(history->favorites_rom[i]) || path_has_value(history->favorites_disk[i]))) {
place = i;
break;
}
}
// if no free space then rotate the favorite list (first in first out)
// and set the place to add at the end of the list
if(place == -1) {
history_favorite_rotate(history);
place = FAVORITES_COUNT - 1;
}
history_favorite_insert(history, place, rom, disk);
history_save(history);
}
void history_favorite_remove(history_t *history, int location)
{
if(location >= 0 && location < FAVORITES_COUNT) {
if(path_has_value(history->favorites_rom[location])) {
path_free(history->favorites_rom[location]);
history->favorites_rom[location] = path_create("");
}
if(path_has_value(history->favorites_disk[location])) {
path_free(history->favorites_disk[location]);
history->favorites_disk[location] = path_create("");
}
}
}

35
src/menu/rom_history.h Normal file
View File

@ -0,0 +1,35 @@
/**
* @file rom_history.h
* @brief Menu History
* @ingroup menu
*/
#ifndef HISTORY_H__
#define HISTORY_H__
#include "path.h"
#define FAVORITES_COUNT 5
/** @brief Settings Structure */
typedef struct {
path_t* last_rom;
path_t* last_disk;
path_t* favorites_rom[FAVORITES_COUNT];
path_t* favorites_disk[FAVORITES_COUNT];
} history_t;
/** @brief Init history path */
void history_init (char *path);
/** @brief The history to load */
void history_load (history_t *history);
/** @brief The history to save */
void history_save (history_t *history);
void history_last_rom_set(history_t *history, path_t* disk_path, path_t* rom_path);
void history_favorite_add(history_t *history, path_t* rom, path_t* disk);
void history_favorite_remove(history_t *history, int location);
#endif

View File

@ -252,4 +252,6 @@ void ui_components_boxart_free(component_boxart_t *b);
*/
void ui_components_boxart_draw(component_boxart_t *b);
void ui_components_main_text_draw_location (float x, float y, char *fmt, ...);
#endif /* UI_COMPONENTS_H__ */

View File

@ -195,3 +195,33 @@ void ui_components_actions_bar_text_draw (rdpq_align_t align, rdpq_valign_t vali
free(formatted);
}
}
void ui_components_main_text_draw_location (float x, float y, char *fmt, ...) {
char buffer[1024];
size_t nbytes = sizeof(buffer);
va_list va;
va_start(va, fmt);
char *formatted = vasnprintf(buffer, &nbytes, fmt, va);
va_end(va);
rdpq_text_printn(
&(rdpq_textparms_t) {
.width = VISIBLE_AREA_WIDTH - (TEXT_MARGIN_HORIZONTAL * 2),
.height = LAYOUT_ACTIONS_SEPARATOR_Y - OVERSCAN_HEIGHT - (TEXT_MARGIN_VERTICAL * 2),
.align = ALIGN_LEFT,
.valign = VALIGN_TOP,
.wrap = WRAP_ELLIPSES,
.line_spacing = TEXT_LINE_SPACING_ADJUST,
},
FNT_DEFAULT,
VISIBLE_AREA_X0 + TEXT_MARGIN_HORIZONTAL + x,
VISIBLE_AREA_Y0 + TEXT_MARGIN_VERTICAL + TEXT_OFFSET_VERTICAL + y,
formatted,
nbytes
);
if (formatted != buffer) {
free(formatted);
}
}

View File

@ -358,6 +358,19 @@ static void process (menu_t *menu) {
} else if (menu->actions.settings) {
ui_components_context_menu_show(&settings_context_menu);
sound_play_effect(SFX_SETTING);
} else if (menu->actions.favorite) {
menu->next_mode = MENU_MODE_FAVORITE;
sound_play_effect(SFX_ENTER);
} else if (menu->actions.load_last) {
if(path_has_value(menu->history.last_disk)) {
menu->load.load_last = true;
menu->next_mode = MENU_MODE_LOAD_DISK;
sound_play_effect(SFX_ENTER);
} else if (path_has_value(menu->history.last_rom)) {
menu->load.load_last = true;
menu->next_mode = MENU_MODE_LOAD_ROM;
sound_play_effect(SFX_ENTER);
}
}
}
@ -403,12 +416,16 @@ static void draw (menu_t *menu, surface_t *d) {
if (menu->current_time >= 0) {
ui_components_actions_bar_text_draw(
ALIGN_CENTER, VALIGN_TOP,
"\n"
"%s",
ctime(&menu->current_time)
);
}
ui_components_actions_bar_text_draw(
ALIGN_CENTER, VALIGN_BOTTOM,
"<C Load Last | C> Favorite"
);
ui_components_context_menu_draw(&entry_context_menu);
ui_components_context_menu_draw(&settings_context_menu);

149
src/menu/views/favorite.c Normal file
View File

@ -0,0 +1,149 @@
#include <stdarg.h>
#include "views.h"
#include "../rom_history.h"
#include "../fonts.h"
#include "../ui_components/constants.h"
#include "../sound.h"
static int selected_favorite = -1;
static void favorite_reset_selected(menu_t* menu) {
selected_favorite = -1;
for(int i=0;i<FAVORITES_COUNT;i++) {
if(path_has_value(menu->history.favorites_rom[i]) || path_has_value(menu->history.favorites_disk[i])) {
selected_favorite = i;
break;
}
}
}
static void process(menu_t* menu) {
if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
} else if(menu->actions.go_down) {
int last_favorite = selected_favorite;
do
{
selected_favorite++;
if(selected_favorite >= FAVORITES_COUNT) {
selected_favorite = last_favorite;
break;
} else if(path_has_value(menu->history.favorites_rom[selected_favorite]) || path_has_value(menu->history.favorites_disk[selected_favorite])) {
sound_play_effect(SFX_CURSOR);
break;
}
} while (true);
} else if(menu->actions.go_up) {
int last_favorite = selected_favorite;
do
{
selected_favorite--;
if(selected_favorite < 0) {
selected_favorite = last_favorite;
break;
} else if(path_has_value(menu->history.favorites_rom[selected_favorite]) || path_has_value(menu->history.favorites_disk[selected_favorite])) {
sound_play_effect(SFX_CURSOR);
break;
}
} while (true);
} else if(menu->actions.enter && selected_favorite != -1) {
menu->load.load_favorite = selected_favorite;
if(path_has_value(menu->history.favorites_disk[selected_favorite])) {
menu->next_mode = MENU_MODE_LOAD_DISK;
sound_play_effect(SFX_ENTER);
} else if(path_has_value(menu->history.favorites_rom[selected_favorite])) {
menu->next_mode = MENU_MODE_LOAD_ROM;
sound_play_effect(SFX_ENTER);
}
} else if(menu->actions.options && selected_favorite != -1) {
history_favorite_remove(&menu->history, selected_favorite);
favorite_reset_selected(menu);
sound_play_effect(SFX_SETTING);
}
}
static void draw_favorites(menu_t *menu, surface_t *display) {
float y = 24;
float x = 10;
if(selected_favorite != -1) {
float highlight_y = 32 + y + (selected_favorite * 16 * 2);
ui_components_box_draw(
VISIBLE_AREA_X0,
highlight_y,
VISIBLE_AREA_X0 + FILE_LIST_HIGHLIGHT_WIDTH,
highlight_y + 32,
FILE_LIST_HIGHLIGHT_COLOR
);
}
for(int i=0;i < FAVORITES_COUNT; i++)
{
ui_components_main_text_draw_location(x, y, "%d :", (i+1));
if(path_has_value(menu->history.favorites_rom[i])) {
ui_components_main_text_draw_location(x + 64, y, "%s", path_last_get(menu->history.favorites_rom[i]));
}
y += 16;
if(path_has_value(menu->history.favorites_disk[i])) {
ui_components_main_text_draw_location(x + 64, y,"%s", path_last_get(menu->history.favorites_disk[i]));
}
y += 16;
}
}
static void draw(menu_t *menu, surface_t *display) {
rdpq_attach(display, NULL);
ui_components_background_draw();
ui_components_layout_draw();
ui_components_main_text_draw(
ALIGN_CENTER, VALIGN_TOP,
"Favorites");
draw_favorites(menu, display);
if(selected_favorite != -1) {
ui_components_actions_bar_text_draw(
ALIGN_LEFT, VALIGN_TOP,
"A: Load Favorite\n"
"B: Exit"
);
ui_components_actions_bar_text_draw(
ALIGN_RIGHT, VALIGN_TOP,
"R: Remove Favorite"
);
} else {
ui_components_actions_bar_text_draw(
ALIGN_LEFT, VALIGN_TOP,
"\n"
"B: Exit"
);
}
rdpq_detach_show();
}
void view_favorite_init (menu_t *menu) {
favorite_reset_selected(menu);
}
void view_favorite_display (menu_t *menu, surface_t *display) {
process(menu);
draw(menu, display);
}

View File

@ -3,6 +3,7 @@
#include "boot/boot.h"
#include "../sound.h"
#include "views.h"
#include "../rom_history.h"
static bool load_disk_with_rom;
@ -39,6 +40,8 @@ static void process (menu_t *menu) {
} else if (menu->actions.back) {
sound_play_effect(SFX_EXIT);
menu->next_mode = MENU_MODE_BROWSER;
} else if (menu->actions.favorite) {
history_favorite_add(&menu->history, menu->load.rom_path, NULL);
}
}
@ -86,6 +89,12 @@ static void draw (menu_t *menu, surface_t *d) {
"B: Exit"
);
ui_components_actions_bar_text_draw(
ALIGN_CENTER, VALIGN_TOP,
"\n"
"C>: Favorite"
);
if (menu->load.rom_path) {
ui_components_actions_bar_text_draw(
ALIGN_RIGHT, VALIGN_TOP,
@ -132,6 +141,7 @@ static void load (menu_t *menu) {
return;
}
history_last_rom_set(&menu->history, menu->load.rom_path, menu->load.disk_path);
menu->next_mode = MENU_MODE_BOOT;
if (load_disk_with_rom) {

View File

@ -5,9 +5,11 @@
#include "views.h"
#include <string.h>
#include "utils/fs.h"
#include "../rom_history.h"
static bool show_extra_info_message = false;
static component_boxart_t *boxart;
static char* name = NULL;
static char *convert_error_message (rom_err_t err) {
switch (err) {
@ -240,7 +242,7 @@ static void draw (menu_t *menu, surface_t *d) {
"N64 ROM information\n"
"\n"
"%s",
menu->browser.entry->name
name
);
ui_components_main_text_draw(
@ -334,6 +336,8 @@ static void load (menu_t *menu) {
return;
}
history_last_rom_set(&menu->history, menu->load.rom_path, NULL);
menu->next_mode = MENU_MODE_BOOT;
menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM;
@ -359,7 +363,15 @@ void view_load_rom_init (menu_t *menu) {
path_free(menu->load.rom_path);
}
menu->load.rom_path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
if(menu->load.load_last) {
menu->load.rom_path = path_clone(menu->history.last_rom);
} else if(menu->load.load_favorite != -1) {
menu->load.rom_path = path_clone(menu->history.favorites_rom[menu->load.load_favorite]);
} else {
menu->load.rom_path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
}
name = path_last_get(menu->load.rom_path);
}
rom_err_t err = rom_info_load(menu->load.rom_path, &menu->load.rom_info);

View File

@ -65,7 +65,10 @@ void view_error_display (menu_t *menu, surface_t *display);
void view_fault_init (menu_t *menu);
void view_fault_display (menu_t *menu, surface_t *display);
void view_favorite_init (menu_t *menu);
void menu_show_error (menu_t *menu, char *error_message);
void view_favorite_display (menu_t *menu, surface_t *display);
/** @} */ /* view */