Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[develop] Add ROM favorites and history tabs to file browser #168

Merged
merged 46 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
16bbd0c
Basic Last Game and Favorties
thegouldfish Nov 30, 2024
0d6fe84
History and last game working
thegouldfish Dec 3, 2024
724f40f
Update favorite.c
thegouldfish Dec 4, 2024
42b9bd7
Update menu.c
thegouldfish Dec 4, 2024
7b4bf24
Update views.h
thegouldfish Dec 4, 2024
092b009
Merge branch 'develop' into history_develop
networkfusion Dec 4, 2024
c2be0c2
Update load_rom.c
thegouldfish Dec 4, 2024
1fecd26
big refactor
thegouldfish Dec 6, 2024
05b17e8
Added favorite removing
thegouldfish Dec 8, 2024
3ad6247
Tab spacing
thegouldfish Dec 8, 2024
77ea002
refactor
thegouldfish Dec 9, 2024
0d00291
Merge branch 'develop' into history_develop
thegouldfish Dec 11, 2024
808bc60
Tidy up
thegouldfish Dec 11, 2024
6b25faa
Merge branch 'develop' into history_develop
thegouldfish Dec 23, 2024
622be1b
Merge branch 'develop' into history_develop
thegouldfish Dec 26, 2024
8eb5ecf
Adding in Context menu for disk info screen
thegouldfish Dec 26, 2024
00aca02
Merge branch 'develop' into history_develop
thegouldfish Dec 27, 2024
1e31712
Tidying up the code for drawing tabs
thegouldfish Dec 27, 2024
38a5385
Merge branch 'develop' into history_develop
networkfusion Dec 30, 2024
ff8c341
Merge branch 'develop' into history_develop
networkfusion Dec 30, 2024
f782295
Tidy up and bug fixes
thegouldfish Dec 30, 2024
942a10f
Review changes
networkfusion Dec 31, 2024
c52aa9b
Code style changes
networkfusion Dec 31, 2024
9e302be
Delete New Text Document.txt
networkfusion Dec 31, 2024
5654755
Update history_favorites.c
thegouldfish Dec 31, 2024
67c85a3
Merge branch 'history_develop' of https://github.com/thegouldfish/N64…
thegouldfish Dec 31, 2024
eb401b0
Update load_rom.c
thegouldfish Dec 31, 2024
30750cd
Minor style improvements
networkfusion Dec 31, 2024
11b5fbe
Merge branch 'develop' into history_develop
thegouldfish Jan 2, 2025
5ce7716
fix ui_components_border_draw_internal name
networkfusion Jan 2, 2025
f87f9c3
rename name to rom_filename
networkfusion Jan 2, 2025
9f74160
Improve var name
networkfusion Jan 3, 2025
86eb8cf
Draw tabs before border
networkfusion Jan 3, 2025
c3da2d5
Merge branch 'develop' into history_develop
networkfusion Jan 3, 2025
774572e
minor improvement
networkfusion Jan 3, 2025
2b07f78
Update bookkeeping.h
networkfusion Jan 3, 2025
9f6b771
Update history_favorites.c
networkfusion Jan 3, 2025
0eaf0e0
Update context_menu.c
thegouldfish Jan 4, 2025
4db6b34
Update constants.h
thegouldfish Jan 4, 2025
0c46176
Update bookkeeping.h
thegouldfish Jan 4, 2025
2f095ea
Fixes layout issues in various menu pages
networkfusion Jan 4, 2025
a4f4258
Update load_disk.c
thegouldfish Jan 4, 2025
e533517
Code style
networkfusion Jan 4, 2025
74a6123
Code style
networkfusion Jan 4, 2025
fbd200b
Fix bookkeeping file-list highlight
networkfusion Jan 4, 2025
ab5461d
Remove debug code
networkfusion Jan 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ SRCS = \
libs/miniz/miniz_zip.c \
libs/miniz/miniz.c \
menu/actions.c \
menu/bookkeeping.c \
menu/cart_load.c \
menu/disk_info.c \
menu/fonts.c \
Expand All @@ -56,12 +57,14 @@ SRCS = \
menu/ui_components/common.c \
menu/ui_components/context_menu.c \
menu/ui_components/file_list.c \
menu/ui_components/tabs.c \
menu/usb_comm.c \
menu/views/browser.c \
menu/views/credits.c \
menu/views/error.c \
menu/views/fault.c \
menu/views/file_info.c \
menu/views/history_favorites.c \
menu/views/image_viewer.c \
menu/views/text_viewer.c \
menu/views/load_disk.c \
Expand Down
Empty file added New Text Document.txt
Empty file.
6 changes: 6 additions & 0 deletions src/menu/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.previous_tab = false;
menu->actions.next_tab = false;
}

static void actions_update_direction (menu_t *menu) {
Expand Down Expand Up @@ -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.previous_tab = true;
} else if (pressed.c_right) {
menu->actions.next_tab = true;
}
}

Expand Down
204 changes: 204 additions & 0 deletions src/menu/bookkeeping.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#include <libdragon.h>
#include <mini.c/src/mini.h>

#include "bookkeeping.h"
#include "utils/fs.h"
#include "path.h"

static char *history_path = NULL;

static path_t* empty_path = NULL;
static bookkeeping_t init;

/** @brief Init history path */
void bookkeeping_init (char *path) {
if (history_path) {
free(history_path);
}
history_path = strdup(path);
empty_path = path_create("");
}


void bookkeeping_ini_load_list(bookkeeping_item_t* list, int count, mini_t* ini, const char* group)
{
char buf[64];
for(int i=0;i<count; i++) {
sprintf(buf,"%d_primary_path", i);
list[i].primary_path = path_create(mini_get_string(ini, group, buf, ""));

sprintf(buf,"%d_secondary_path", i);
list[i].secondary_path = path_create(mini_get_string(ini, group, buf, ""));

sprintf(buf,"%d_type", i);
list[i].bookkeeping_type = mini_get_int(ini, group, buf, BOOKKEEPING_TYPE_EMPTY);
}
}

/** @brief The history to load */
void bookkeeping_load (bookkeeping_t *history) {
if (!file_exists(history_path)) {
bookkeeping_save(&init);
}

mini_t *ini = mini_try_load(history_path);
bookkeeping_ini_load_list(history->history_items, HISTORY_COUNT, ini, "history");
bookkeeping_ini_load_list(history->favorite_items, HISTORY_COUNT, ini, "favorite");


mini_free(ini);
}

static void bookkeeping_ini_save_list(bookkeeping_item_t* list, int count, mini_t* ini, const char* group)
{
char buf[64];
for(int i=0;i<count; i++) {
sprintf(buf,"%d_primary_path", i);
path_t* path = list[i].primary_path;
mini_set_string(ini, group, buf, path != NULL ? path_get(path) : "");

sprintf(buf,"%d_secondary_path", i);
path = list[i].secondary_path;
mini_set_string(ini, group, buf, path != NULL ? path_get(path) : "");

sprintf(buf,"%d_type", i);
mini_set_int(ini, group, buf, list[i].bookkeeping_type);
}
}

/** @brief The history to save */
void bookkeeping_save (bookkeeping_t *history)
{
mini_t *ini = mini_create(history_path);

bookkeeping_ini_save_list(history->history_items, HISTORY_COUNT, ini, "history");
bookkeeping_ini_save_list(history->favorite_items, FAVORITES_COUNT, ini, "favorite");

mini_save(ini, MINI_FLAGS_SKIP_EMPTY_GROUPS);
mini_free(ini);
}

static bool bookkeeping_item_match(bookkeeping_item_t* left, bookkeeping_item_t* right) {
if(left != NULL && right != NULL) {
return path_are_match(left->primary_path, right->primary_path) && path_are_match(left->secondary_path, right->secondary_path) && left->bookkeeping_type == right->bookkeeping_type;
}

return false;
}

static void bookkeeping_clear_item(bookkeeping_item_t* item, bool leave_null) {
if(item->primary_path != NULL){
path_free(item->primary_path);

if(leave_null) {
item->primary_path = NULL;
} else {
item->primary_path = path_create("");
}
}
if(item->secondary_path != NULL){
path_free(item->secondary_path);

if(leave_null) {
item->secondary_path = NULL;
} else {
item->secondary_path = path_create("");
}
}
item->bookkeeping_type = BOOKKEEPING_TYPE_EMPTY;
}

static void bookkeeping_copy_item(bookkeeping_item_t* source, bookkeeping_item_t* destination) {
bookkeeping_clear_item(destination, true);

destination->primary_path = path_clone(source->primary_path);
destination->secondary_path = source->secondary_path != NULL ? path_clone(source->secondary_path) : path_create("");
destination->bookkeeping_type = source->bookkeeping_type;
}

static void bookkeeping_move_items_down(bookkeeping_item_t* list, int start, int end) {
int current = end;

do {
if(current <= start || current < 0) {
break;
}

bookkeeping_copy_item(&list[current - 1], &list[current]);
current--;
} while(true);
}


static void bookkeeping_move_items_up(bookkeeping_item_t* list, int start, int end) {
int current = start;

do {
if(current > end) {
break;
}

bookkeeping_copy_item(&list[current + 1], &list[current]);
current++;
} while(true);
}


static void bookkeeping_insert_top(bookkeeping_item_t* list, int count, bookkeeping_item_t* new_item) {
// if it matches the top of the list already then nothing to do
if(bookkeeping_item_match(&list[0], new_item)) {
return;
}

// if the top isn't empty then we need to move things around
if(list[0].bookkeeping_type != BOOKKEEPING_TYPE_EMPTY) {
int found_at = -1;
for(int i=1; i < count; i++) {
if(bookkeeping_item_match(&list[i], new_item)){
found_at = i;
break;
}
}

if(found_at == -1) {
bookkeeping_move_items_down(list, 0, count - 1);
} else {
bookkeeping_move_items_down(list, 0, found_at);
}
}

bookkeeping_copy_item(new_item, &list[0]);
}

void bookkeeping_history_add(bookkeeping_t *bookkeeping, path_t* primary_path, path_t* secondary_path, bookkeeping_item_types_t type ) {
bookkeeping_item_t new_item = {
.primary_path = primary_path,
.secondary_path = secondary_path,
.bookkeeping_type = type
};

bookkeeping_insert_top(bookkeeping->history_items, HISTORY_COUNT, &new_item);
bookkeeping_save(bookkeeping);
}


void bookkeeping_favorite_add(bookkeeping_t *bookkeeping, path_t* primary_path, path_t* secondary_path, bookkeeping_item_types_t type ) {
bookkeeping_item_t new_item = {
.primary_path = primary_path,
.secondary_path = secondary_path,
.bookkeeping_type = type
};

bookkeeping_insert_top(bookkeeping->favorite_items, FAVORITES_COUNT, &new_item);
bookkeeping_save(bookkeeping);
}

void bookkeeping_favorite_remove(bookkeeping_t *bookkeeping, int selection) {
if(bookkeeping->favorite_items[selection].bookkeeping_type != BOOKKEEPING_TYPE_EMPTY) {

bookkeeping_move_items_up(bookkeeping->favorite_items, selection, FAVORITES_COUNT -1);
bookkeeping_clear_item(&bookkeeping->favorite_items[FAVORITES_COUNT -1], false);

bookkeeping_save(bookkeeping);
}
}
52 changes: 52 additions & 0 deletions src/menu/bookkeeping.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* @file rom_history.h
* @brief Menu History
* @ingroup menu
*/

#ifndef HISTORY_H__
#define HISTORY_H__

#include "path.h"


#define FAVORITES_COUNT 5
#define HISTORY_COUNT 5

typedef enum {
BOOKKEEPING_TYPE_EMPTY,
BOOKKEEPING_TYPE_ROM,
BOOKKEEPING_TYPE_DISK,
} bookkeeping_item_types_t;

typedef struct {
path_t* primary_path;
path_t* secondary_path;

bookkeeping_item_types_t bookkeeping_type;

} bookkeeping_item_t;

/** @brief history Structure */
typedef struct {
bookkeeping_item_t history_items[HISTORY_COUNT];

bookkeeping_item_t favorite_items[HISTORY_COUNT];
} bookkeeping_t;


/** @brief Init history path */
void bookkeeping_init (char *path);

/** @brief The history to load */
void bookkeeping_load (bookkeeping_t *history);

/** @brief The history to save */
void bookkeeping_save (bookkeeping_t *history);

void bookkeeping_history_add(bookkeeping_t *bookkeeping, path_t* primary_path, path_t* secondary_path, bookkeeping_item_types_t type );

void bookkeeping_favorite_add(bookkeeping_t *bookkeeping, path_t* primary_path, path_t* secondary_path, bookkeeping_item_types_t type );
void bookkeeping_favorite_remove(bookkeeping_t *bookkeeping, int selection);

#endif
10 changes: 10 additions & 0 deletions src/menu/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
bookkeeping_init(path_get(path));
bookkeeping_load(&menu->bookkeeping);
menu->load.load_history = -1;
menu->load.load_favorite = -1;
path_pop(path);

resolution_t resolution = {
.width = 640,
.height = 480,
Expand Down Expand Up @@ -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 },
{ MENU_MODE_HISTORY, view_history_init, view_history_display }
};

static view_t *menu_get_view (menu_mode_t id) {
Expand Down
8 changes: 8 additions & 0 deletions src/menu/menu_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "path.h"
#include "rom_info.h"
#include "settings.h"
#include "bookkeeping.h"


/** @brief Menu mode enumeration */
Expand All @@ -38,6 +39,8 @@ typedef enum {
MENU_MODE_ERROR,
MENU_MODE_FAULT,
MENU_MODE_BOOT,
MENU_MODE_FAVORITE,
MENU_MODE_HISTORY
} menu_mode_t;

/** @brief File entry type enumeration */
Expand Down Expand Up @@ -67,6 +70,7 @@ typedef struct {

const char *storage_prefix;
settings_t settings;
bookkeeping_t bookkeeping;
boot_params_t *boot_params;

char *error_message;
Expand All @@ -86,6 +90,8 @@ typedef struct {
bool options;
bool settings;
bool lz_context;
bool previous_tab;
bool next_tab;
} actions;

struct {
Expand All @@ -103,6 +109,8 @@ typedef struct {
rom_info_t rom_info;
path_t *disk_path;
disk_info_t disk_info;
int load_history;
int load_favorite;
} load;

struct {
Expand Down
Loading