big refactor

refactored most of the history / favorite code to now be "bookkeeping".
this now uses a common struct to hold the required paths and the record type (to open up future work for emus).
This commit is contained in:
Ross Gouldthorpe 2024-12-06 23:10:25 +00:00
parent c2be0c2f20
commit 1fecd26f0b
18 changed files with 451 additions and 322 deletions

View File

@ -57,6 +57,7 @@ SRCS = \
menu/ui_components/common.c \ menu/ui_components/common.c \
menu/ui_components/context_menu.c \ menu/ui_components/context_menu.c \
menu/ui_components/file_list.c \ menu/ui_components/file_list.c \
menu/ui_components/tabs.c \
menu/usb_comm.c \ menu/usb_comm.c \
menu/views/browser.c \ menu/views/browser.c \
menu/views/credits.c \ menu/views/credits.c \

0
New Text Document.txt Normal file
View File

View File

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

View File

@ -72,9 +72,9 @@ static void menu_init (boot_params_t *boot_params) {
path_pop(path); path_pop(path);
path_push(path, MENU_HISTORY_FILE); path_push(path, MENU_HISTORY_FILE);
history_init(path_get(path)); bookkeeping_init(path_get(path));
history_load(&menu->history); bookkeeping_load(&menu->history);
menu->load.load_last = false; menu->load.load_history = -1;
menu->load.load_favorite = -1; menu->load.load_favorite = -1;
path_pop(path); path_pop(path);
@ -158,7 +158,8 @@ static view_t menu_views[] = {
{ MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display }, { MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display },
{ MENU_MODE_ERROR, view_error_init, view_error_display }, { MENU_MODE_ERROR, view_error_init, view_error_display },
{ MENU_MODE_FAULT, view_fault_init, view_fault_display }, { MENU_MODE_FAULT, view_fault_init, view_fault_display },
{ MENU_MODE_FAVORITE, view_favorite_init, view_favorite_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) { static view_t *menu_get_view (menu_mode_t id) {

View File

@ -39,7 +39,8 @@ typedef enum {
MENU_MODE_ERROR, MENU_MODE_ERROR,
MENU_MODE_FAULT, MENU_MODE_FAULT,
MENU_MODE_BOOT, MENU_MODE_BOOT,
MENU_MODE_FAVORITE MENU_MODE_FAVORITE,
MENU_MODE_HISTORY
} menu_mode_t; } menu_mode_t;
/** @brief File entry type enumeration */ /** @brief File entry type enumeration */
@ -69,7 +70,7 @@ typedef struct {
const char *storage_prefix; const char *storage_prefix;
settings_t settings; settings_t settings;
history_t history; bookkeeping_t history;
boot_params_t *boot_params; boot_params_t *boot_params;
char *error_message; char *error_message;
@ -89,8 +90,8 @@ typedef struct {
bool options; bool options;
bool settings; bool settings;
bool lz_context; bool lz_context;
bool favorite; bool previous_tab;
bool load_last; bool next_tab;
} actions; } actions;
struct { struct {
@ -108,7 +109,7 @@ typedef struct {
rom_info_t rom_info; rom_info_t rom_info;
path_t *disk_path; path_t *disk_path;
disk_info_t disk_info; disk_info_t disk_info;
bool load_last; int load_history;
int load_favorite; int load_favorite;
} load; } load;

View File

@ -150,3 +150,13 @@ bool path_has_value(path_t *path) {
} }
return false; return false;
} }
bool path_are_match(path_t *left, path_t *right) {
if(!path_has_value(left) && !path_has_value(right)) {
return true;
} else if(path_has_value(left) && path_has_value(right)) {
return (strcmp(path_get(left), path_get(right)) == 0);
} else {
return false;
}
}

View File

@ -34,5 +34,6 @@ char *path_ext_get (path_t *path);
void path_ext_remove (path_t *path); void path_ext_remove (path_t *path);
void path_ext_replace (path_t *path, char *ext); void path_ext_replace (path_t *path, char *ext);
bool path_has_value(path_t *path); bool path_has_value(path_t *path);
bool path_are_match(path_t *left, path_t *right);
#endif #endif

View File

@ -10,10 +10,10 @@
static char *history_path = NULL; static char *history_path = NULL;
static path_t* empty_path = NULL; static path_t* empty_path = NULL;
static history_t init; static bookkeeping_t init;
/** @brief Init history path */ /** @brief Init history path */
void history_init (char *path) { void bookkeeping_init (char *path) {
if (history_path) { if (history_path) {
free(history_path); free(history_path);
} }
@ -21,213 +21,151 @@ void history_init (char *path) {
empty_path = path_create(""); 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, HISTORY_TYPE_EMPTY);
}
}
/** @brief The history to load */ /** @brief The history to load */
void history_load (history_t *history) { void bookkeeping_load (bookkeeping_t *history) {
if (!file_exists(history_path)) { if (!file_exists(history_path)) {
history_save(&init); bookkeeping_save(&init);
} }
mini_t *ini = mini_try_load(history_path); mini_t *ini = mini_try_load(history_path);
history->last_rom = path_create(mini_get_string(ini, "history", "last_rom", "")); bookkeeping_ini_load_list(history->history_items, HISTORY_COUNT, ini, "history");
history->last_disk = path_create(mini_get_string(ini, "history", "last_disk", "")); bookkeeping_ini_load_list(history->favorite_items, HISTORY_COUNT, ini, "favorite");
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); 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 */ /** @brief The history to save */
void history_save (history_t *history) void bookkeeping_save (bookkeeping_t *history)
{ {
mini_t *ini = mini_create(history_path); mini_t *ini = mini_create(history_path);
mini_set_string(ini, "history", "last_rom", history->last_rom != NULL ? path_get(history->last_rom) : ""); bookkeeping_ini_save_list(history->history_items, HISTORY_COUNT, ini, "history");
mini_set_string(ini, "history", "last_disk", history->last_disk != NULL ? path_get(history->last_disk) : ""); bookkeeping_ini_save_list(history->favorite_items, FAVORITES_COUNT, ini, "favorite");
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_save(ini, MINI_FLAGS_SKIP_EMPTY_GROUPS);
mini_free(ini); mini_free(ini);
} }
static bool bookkeeping_item_match(bookkeeping_item_t* left, bookkeeping_item_t* right) {
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) { if(left != NULL && right != NULL) {
matches = (strcmp(path_get(left), path_get(right)) == 0); 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 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; return false;
} }
void history_favorite_add(history_t *history, path_t* rom, path_t* disk) { static void bookkeeping_clear_item(bookkeeping_item_t* item) {
// if the game is already in the favorite list then don't add again if(item->primary_path != NULL){
path_free(item->primary_path);
if(rom == NULL) {
rom = empty_path;
} }
if(disk == NULL) { if(item->secondary_path != NULL){
disk = empty_path; path_free(item->secondary_path);
}
item->bookkeeping_type = HISTORY_TYPE_EMPTY;
} }
if(history_favorite_exists(history, rom, disk)) { static void bookkeeping_copy_item(bookkeeping_item_t* source, bookkeeping_item_t* destination){
bookkeeping_clear_item(destination);
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_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; return;
} }
// look for a free space in the list // if the top isn't empty then we need to move things around
int place = -1; if(list[0].bookkeeping_type != HISTORY_TYPE_EMPTY) {
for(int i=0;i < FAVORITES_COUNT;i++) { int found_at = -1;
if(!(path_has_value(history->favorites_rom[i]) || path_has_value(history->favorites_disk[i]))) { for(int i=1; i < count; i++) {
place = i; if(bookkeeping_item_match(&list[i], new_item)){
found_at = i;
break; break;
} }
} }
// if no free space then rotate the favorite list (first in first out) if(found_at == -1) {
// and set the place to add at the end of the list bookkeeping_move_items_down(list, 0, count - 1);
if(place == -1) { } else {
history_favorite_rotate(history); bookkeeping_move_items_down(list, 0, found_at);
place = FAVORITES_COUNT - 1; }
} }
history_favorite_insert(history, place, rom, disk); bookkeeping_copy_item(new_item, &list[0]);
history_save(history);
} }
void history_favorite_remove(history_t *history, int location) 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 = {
if(location >= 0 && location < FAVORITES_COUNT) { .primary_path = primary_path,
if(path_has_value(history->favorites_rom[location])) { .secondary_path = secondary_path,
path_free(history->favorites_rom[location]); .bookkeeping_type = type
history->favorites_rom[location] = path_create(""); };
bookkeeping_insert_top(bookkeeping->history_items, HISTORY_COUNT, &new_item);
bookkeeping_save(bookkeeping);
} }
if(path_has_value(history->favorites_disk[location])) {
path_free(history->favorites_disk[location]); void bookkeeping_favorite_add(bookkeeping_t *bookkeeping, path_t* primary_path, path_t* secondary_path, bookkeeping_item_types_t type ) {
history->favorites_disk[location] = path_create(""); 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);
} }

View File

@ -9,27 +9,48 @@
#include "path.h" #include "path.h"
#define FAVORITES_COUNT 5 #define FAVORITES_COUNT 5
#define HISTORY_COUNT 5
typedef enum {
HISTORY_TYPE_EMPTY,
HISTORY_TYPE_ROM,
HISTORY_TYPE_DISK,
} bookkeeping_item_types_t;
/** @brief Settings Structure */
typedef struct { typedef struct {
path_t* last_rom; path_t* primary_path;
path_t* last_disk; 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;
path_t* favorites_rom[FAVORITES_COUNT];
path_t* favorites_disk[FAVORITES_COUNT];
} history_t;
/** @brief Init history path */ /** @brief Init history path */
void history_init (char *path); void bookkeeping_init (char *path);
/** @brief The history to load */ /** @brief The history to load */
void history_load (history_t *history); void bookkeeping_load (bookkeeping_t *history);
/** @brief The history to save */ /** @brief The history to save */
void history_save (history_t *history); void bookkeeping_save (bookkeeping_t *history);
void history_last_rom_set(history_t *history, path_t* disk_path, path_t* rom_path); //void history_last_rom_set(bookkeeping_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_add(bookkeeping_t *history, path_t* rom, path_t* disk);
void history_favorite_remove(history_t *history, int location); //void history_favorite_remove(bookkeeping_t *history, int location);
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 );
#endif #endif

View File

@ -253,5 +253,18 @@ void ui_components_boxart_free(component_boxart_t *b);
void ui_components_boxart_draw(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, ...); void ui_components_main_text_draw_location (float x, float y, char *fmt, ...);
/**
*
*/
void ui_components_tabs_draw(const char** text, int count, int selected );
/**
*
*/
void ui_compontents_tabs_common_draw(int selected);
#endif /* UI_COMPONENTS_H__ */ #endif /* UI_COMPONENTS_H__ */

View File

@ -13,9 +13,10 @@ void ui_components_box_draw (int x0, int y0, int x1, int y1, color_t color) {
rdpq_mode_pop(); rdpq_mode_pop();
} }
void ui_components_border_draw (int x0, int y0, int x1, int y1) {
static void ui_components_border_draw_interal (int x0, int y0, int x1, int y1, color_t color) {
rdpq_mode_push(); rdpq_mode_push();
rdpq_set_mode_fill(BORDER_COLOR); rdpq_set_mode_fill(color);
rdpq_fill_rectangle(x0 - BORDER_THICKNESS, y0 - BORDER_THICKNESS, x1 + BORDER_THICKNESS, y0); rdpq_fill_rectangle(x0 - BORDER_THICKNESS, y0 - BORDER_THICKNESS, x1 + BORDER_THICKNESS, y0);
rdpq_fill_rectangle(x0 - BORDER_THICKNESS, y1, x1 + BORDER_THICKNESS, y1 + BORDER_THICKNESS); rdpq_fill_rectangle(x0 - BORDER_THICKNESS, y1, x1 + BORDER_THICKNESS, y1 + BORDER_THICKNESS);
@ -25,6 +26,10 @@ void ui_components_border_draw (int x0, int y0, int x1, int y1) {
rdpq_mode_pop(); rdpq_mode_pop();
} }
void ui_components_border_draw (int x0, int y0, int x1, int y1) {
ui_components_border_draw_interal(x0, y0, x1, y1, BORDER_COLOR);
}
void ui_components_layout_draw (void) { void ui_components_layout_draw (void) {
ui_components_border_draw( ui_components_border_draw(
VISIBLE_AREA_X0, VISIBLE_AREA_X0,
@ -215,8 +220,10 @@ void ui_components_main_text_draw_location (float x, float y, char *fmt, ...) {
.line_spacing = TEXT_LINE_SPACING_ADJUST, .line_spacing = TEXT_LINE_SPACING_ADJUST,
}, },
FNT_DEFAULT, FNT_DEFAULT,
VISIBLE_AREA_X0 + TEXT_MARGIN_HORIZONTAL + x, x,
VISIBLE_AREA_Y0 + TEXT_MARGIN_VERTICAL + TEXT_OFFSET_VERTICAL + y, y,
///VISIBLE_AREA_X0 + TEXT_MARGIN_HORIZONTAL + x,
//VISIBLE_AREA_Y0 + TEXT_MARGIN_VERTICAL + TEXT_OFFSET_VERTICAL + y,
formatted, formatted,
nbytes nbytes
); );
@ -225,3 +232,69 @@ void ui_components_main_text_draw_location (float x, float y, char *fmt, ...) {
free(formatted); free(formatted);
} }
} }
void ui_components_tabs_draw(const char** text, int count, int selected ) {
ui_components_box_draw(
VISIBLE_AREA_X0,
LAYOUT_ACTIONS_SEPARATOR_Y,
VISIBLE_AREA_X1,
LAYOUT_ACTIONS_SEPARATOR_Y + BORDER_THICKNESS,
BORDER_COLOR
);
int x = VISIBLE_AREA_X0;
int y = OVERSCAN_HEIGHT;
int width = 14 * 8;
int height = TAB_HEIGHT;
// first draw the tabs that are not selected
for(int i=0;i< count;i++) {
if(i != selected) {
ui_components_box_draw(
x,
y,
x + width,
y + height,
TAB_INACTIVE_BACKGROUND_COLOR
);
ui_components_border_draw_interal(
x,
y,
x + width,
y + height,
TAB_INACTIVE_BORDER_COLOR
);
ui_components_main_text_draw_location(x + 8, y, (char*)text[i]);
}
x += width;
}
// draw the selected tab
if(selected >= 0 && selected < count) {
x = VISIBLE_AREA_X0 + (width * selected);
ui_components_box_draw(
x,
y,
x + width,
y + height,
TAB_ACTIVE_BACKGROUND_COLOR
);
ui_components_border_draw_interal(
x,
y,
x + width,
y + height,
TAB_ACTIVE_BORDER_COLOR
);
ui_components_main_text_draw_location(x + 8, y, (char*)text[selected]);
}
}

View File

@ -7,6 +7,10 @@
#ifndef COMPONENTS_CONSTANTS_H__ #ifndef COMPONENTS_CONSTANTS_H__
#define COMPONENTS_CONSTANTS_H__ #define COMPONENTS_CONSTANTS_H__
#define TAB_HEIGHT (20)
/** @brief The thickness of borders. */
#define BORDER_THICKNESS (4)
/** @brief The display width. */ /** @brief The display width. */
#define DISPLAY_WIDTH (640) #define DISPLAY_WIDTH (640)
/** @brief The display height. */ /** @brief The display height. */
@ -25,7 +29,7 @@
/** @brief The start position of the visible display on the X axis. */ /** @brief The start position of the visible display on the X axis. */
#define VISIBLE_AREA_X0 (OVERSCAN_WIDTH) #define VISIBLE_AREA_X0 (OVERSCAN_WIDTH)
/** @brief The start position of the visible display on the Y axis. */ /** @brief The start position of the visible display on the Y axis. */
#define VISIBLE_AREA_Y0 (OVERSCAN_HEIGHT) #define VISIBLE_AREA_Y0 (OVERSCAN_HEIGHT + TAB_HEIGHT + BORDER_THICKNESS)
/** @brief The end position of the visible display on the X axis. */ /** @brief The end position of the visible display on the X axis. */
#define VISIBLE_AREA_X1 (DISPLAY_WIDTH - OVERSCAN_WIDTH) #define VISIBLE_AREA_X1 (DISPLAY_WIDTH - OVERSCAN_WIDTH)
/** @brief The end position of the visible display on the Y axis. */ /** @brief The end position of the visible display on the Y axis. */
@ -36,8 +40,7 @@
/** @brief The height of the visible display. */ /** @brief The height of the visible display. */
#define VISIBLE_AREA_HEIGHT (VISIBLE_AREA_Y1 - VISIBLE_AREA_Y0) #define VISIBLE_AREA_HEIGHT (VISIBLE_AREA_Y1 - VISIBLE_AREA_Y0)
/** @brief The thickness of borders. */
#define BORDER_THICKNESS (4)
#define LAYOUT_ACTIONS_SEPARATOR_Y (400) #define LAYOUT_ACTIONS_SEPARATOR_Y (400)
@ -101,14 +104,14 @@
/** @brief The scroll bar width. */ /** @brief The scroll bar width. */
#define LIST_SCROLLBAR_WIDTH (12) #define LIST_SCROLLBAR_WIDTH (12)
/** @brief The scroll bar height. */ /** @brief The scroll bar height. */
#define LIST_SCROLLBAR_HEIGHT (LAYOUT_ACTIONS_SEPARATOR_Y - OVERSCAN_HEIGHT) #define LIST_SCROLLBAR_HEIGHT (LAYOUT_ACTIONS_SEPARATOR_Y - OVERSCAN_HEIGHT - TAB_HEIGHT)
/** @brief The scroll bar position on the X axis. */ /** @brief The scroll bar position on the X axis. */
#define LIST_SCROLLBAR_X (VISIBLE_AREA_X1 - LIST_SCROLLBAR_WIDTH) #define LIST_SCROLLBAR_X (VISIBLE_AREA_X1 - LIST_SCROLLBAR_WIDTH)
/** @brief The scroll bar position on the Y axis. */ /** @brief The scroll bar position on the Y axis. */
#define LIST_SCROLLBAR_Y (VISIBLE_AREA_Y0) #define LIST_SCROLLBAR_Y (VISIBLE_AREA_Y0)
/** @brief The maximum amount of file list entries. */ /** @brief The maximum amount of file list entries. */
#define LIST_ENTRIES (19) #define LIST_ENTRIES (18)
/** @brief The maximum width available for a file list entry. */ /** @brief The maximum width available for a file list entry. */
#define FILE_LIST_MAX_WIDTH (480) #define FILE_LIST_MAX_WIDTH (480)
#define FILE_LIST_HIGHLIGHT_WIDTH (VISIBLE_AREA_X1 - VISIBLE_AREA_X0 - LIST_SCROLLBAR_WIDTH) #define FILE_LIST_HIGHLIGHT_WIDTH (VISIBLE_AREA_X1 - VISIBLE_AREA_X0 - LIST_SCROLLBAR_WIDTH)
@ -147,4 +150,10 @@
#define CONTEXT_MENU_HIGHLIGHT_COLOR RGBA32(0x3F, 0x3F, 0x3F, 0xFF) #define CONTEXT_MENU_HIGHLIGHT_COLOR RGBA32(0x3F, 0x3F, 0x3F, 0xFF)
#define TAB_INACTIVE_BORDER_COLOR RGBA32(0x5F, 0x5F, 0x5F, 0xFF)
#define TAB_ACTIVE_BORDER_COLOR RGBA32(0x00, 0x00, 0xFF, 0xFF)
#define TAB_INACTIVE_BACKGROUND_COLOR RGBA32(0x3F, 0x3F, 0x3F, 0xFF)
#define TAB_ACTIVE_BACKGROUND_COLOR RGBA32(0x6F, 0x6F, 0x6F, 0xFF)
#endif #endif

View File

@ -0,0 +1,15 @@
#include "../ui_components.h"
static const char* tabs[3] =
{
"Browser",
"History",
"Favorites"
};
void ui_compontents_tabs_common_draw(int selected)
{
ui_components_tabs_draw(tabs, 3, selected);
}

View File

@ -358,22 +358,12 @@ static void process (menu_t *menu) {
} else if (menu->actions.settings) { } else if (menu->actions.settings) {
ui_components_context_menu_show(&settings_context_menu); ui_components_context_menu_show(&settings_context_menu);
sound_play_effect(SFX_SETTING); sound_play_effect(SFX_SETTING);
} else if (menu->actions.favorite) { } else if (menu->actions.next_tab) {
menu->next_mode = MENU_MODE_HISTORY;
} else if (menu->actions.previous_tab) {
menu->next_mode = MENU_MODE_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);
} }
} }
}
static void draw (menu_t *menu, surface_t *d) { static void draw (menu_t *menu, surface_t *d) {
rdpq_attach(d, NULL); rdpq_attach(d, NULL);
@ -384,6 +374,8 @@ static void draw (menu_t *menu, surface_t *d) {
ui_components_file_list_draw(menu->browser.list, menu->browser.entries, menu->browser.selected); ui_components_file_list_draw(menu->browser.list, menu->browser.entries, menu->browser.selected);
ui_compontents_tabs_common_draw(0);
const char *action = NULL; const char *action = NULL;
if (menu->browser.entry) { if (menu->browser.entry) {
@ -417,14 +409,14 @@ static void draw (menu_t *menu, surface_t *d) {
ui_components_actions_bar_text_draw( ui_components_actions_bar_text_draw(
ALIGN_CENTER, VALIGN_TOP, ALIGN_CENTER, VALIGN_TOP,
"%s" //ctime includes a newline "%s" //ctime includes a newline
"<C Load Last | C> Favorite", "<C Change Tabs C>",
ctime(&menu->current_time) ctime(&menu->current_time)
); );
} else { } else {
ui_components_actions_bar_text_draw( ui_components_actions_bar_text_draw(
ALIGN_CENTER, VALIGN_TOP, ALIGN_CENTER, VALIGN_TOP,
"\n" "\n"
"<C Load Last | C> Favorite" "<C Tabs C>"
); );
} }

View File

@ -5,99 +5,139 @@
#include "../ui_components/constants.h" #include "../ui_components/constants.h"
#include "../sound.h" #include "../sound.h"
static int selected_favorite = -1;
static void favorite_reset_selected(menu_t* menu) { typedef enum {
selected_favorite = -1; BOOKKEEPING_SCREEN_MODE_HISTORY,
BOOKKEEPING_SCREEN_MODE_FAVORITE
} bookkeeping_screen_modes_t;
for(int i=0;i<FAVORITES_COUNT;i++) { static bookkeeping_screen_modes_t screen_mode = -1;
if(path_has_value(menu->history.favorites_rom[i]) || path_has_value(menu->history.favorites_disk[i])) { static int selected_item = -1;
selected_favorite = i; static bookkeeping_item_t* item_list;
static int item_max;
static void reset_selected(menu_t* menu) {
selected_item = -1;
for(int i=0;i<item_max;i++) {
if(item_list[selected_item].bookkeeping_type != HISTORY_TYPE_EMPTY) {
selected_item = i;
break; break;
} }
} }
} }
static void move_next() {
int last = selected_item;
do
{
selected_item++;
if(selected_item >= item_max) {
selected_item = last;
break;
} else if(item_list[selected_item].bookkeeping_type != HISTORY_TYPE_EMPTY) {
sound_play_effect(SFX_CURSOR);
break;
}
} while (true);
}
static void move_back() {
int last = selected_item;
do
{
selected_item--;
if(selected_item < 0) {
selected_item = last;
break;
} else if(item_list[selected_item].bookkeeping_type != HISTORY_TYPE_EMPTY) {
sound_play_effect(SFX_CURSOR);
break;
}
} while (true);
}
static void process(menu_t* menu) { static void process(menu_t* menu) {
if (menu->actions.back) { if(menu->actions.go_down) {
menu->next_mode = MENU_MODE_BROWSER; move_next();
} 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) { } else if(menu->actions.go_up) {
int last_favorite = selected_favorite; move_back();
} else if(menu->actions.enter && selected_item != -1) {
do if(screen_mode == BOOKKEEPING_SCREEN_MODE_FAVORITE) {
{ menu->load.load_favorite = selected_item;
selected_favorite--; } else if(screen_mode == BOOKKEEPING_SCREEN_MODE_HISTORY) {
menu->load.load_history = selected_item;
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])) { if(item_list[selected_item].bookkeeping_type == HISTORY_TYPE_DISK) {
menu->next_mode = MENU_MODE_LOAD_DISK; menu->next_mode = MENU_MODE_LOAD_DISK;
sound_play_effect(SFX_ENTER); sound_play_effect(SFX_ENTER);
} else if(path_has_value(menu->history.favorites_rom[selected_favorite])) { } else if(item_list[selected_item].bookkeeping_type == HISTORY_TYPE_ROM) {
menu->next_mode = MENU_MODE_LOAD_ROM; menu->next_mode = MENU_MODE_LOAD_ROM;
sound_play_effect(SFX_ENTER); sound_play_effect(SFX_ENTER);
} }
} else if(menu->actions.options && selected_favorite != -1) { } else if (menu->actions.previous_tab) {
history_favorite_remove(&menu->history, selected_favorite); if(screen_mode == BOOKKEEPING_SCREEN_MODE_FAVORITE) {
favorite_reset_selected(menu); menu->next_mode = MENU_MODE_HISTORY;
} else if(screen_mode == BOOKKEEPING_SCREEN_MODE_HISTORY) {
menu->next_mode = MENU_MODE_BROWSER;
}
} else if (menu->actions.next_tab) {
if(screen_mode == BOOKKEEPING_SCREEN_MODE_FAVORITE) {
menu->next_mode = MENU_MODE_BROWSER;
} else if(screen_mode == BOOKKEEPING_SCREEN_MODE_HISTORY) {
menu->next_mode = MENU_MODE_FAVORITE;
}
}else if(screen_mode == BOOKKEEPING_SCREEN_MODE_FAVORITE && menu->actions.options && selected_item != -1) {
//history_favorite_remove(&menu->history, selected_item);
reset_selected(menu);
sound_play_effect(SFX_SETTING); sound_play_effect(SFX_SETTING);
} }
} }
static void draw_favorites(menu_t *menu, surface_t *display) { static void draw_favorites(menu_t *menu, surface_t *display) {
float y = 24; float y = VISIBLE_AREA_Y0;
float x = 10; float x = 10 + VISIBLE_AREA_X0;
if(selected_favorite != -1) { if(selected_item != -1) {
float highlight_y = 32 + y + (selected_favorite * 16 * 2); float highlight_y = y + (selected_item * 18 * 2);
ui_components_box_draw( ui_components_box_draw(
VISIBLE_AREA_X0, VISIBLE_AREA_X0,
highlight_y, highlight_y,
VISIBLE_AREA_X0 + FILE_LIST_HIGHLIGHT_WIDTH, VISIBLE_AREA_X0 + FILE_LIST_HIGHLIGHT_WIDTH,
highlight_y + 32, highlight_y + 36,
FILE_LIST_HIGHLIGHT_COLOR FILE_LIST_HIGHLIGHT_COLOR
); );
} }
for(int i=0;i < FAVORITES_COUNT; i++) for(int i=0;i < FAVORITES_COUNT; i++) {
{ if(path_has_value(item_list[i].primary_path)) {
ui_components_main_text_draw_location(x, y, "%d : %s",(i+1), path_last_get(item_list[i].primary_path));
} else {
ui_components_main_text_draw_location(x, y, "%d :", (i+1)); 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; y += 16;
if(path_has_value(menu->history.favorites_disk[i])) { if(path_has_value(item_list[i].secondary_path)) {
ui_components_main_text_draw_location(x + 64, y,"%s", path_last_get(menu->history.favorites_disk[i])); ui_components_main_text_draw_location(x, y," %s", path_last_get(item_list[i].secondary_path));
} }
y += 20; y += 20;
} }
if(screen_mode == BOOKKEEPING_SCREEN_MODE_FAVORITE) {
ui_compontents_tabs_common_draw(2);
} else if(screen_mode == BOOKKEEPING_SCREEN_MODE_HISTORY) {
ui_compontents_tabs_common_draw(1);
}
} }
static void draw(menu_t *menu, surface_t *display) { static void draw(menu_t *menu, surface_t *display) {
@ -107,31 +147,21 @@ static void draw(menu_t *menu, surface_t *display) {
ui_components_layout_draw(); ui_components_layout_draw();
ui_components_main_text_draw(
ALIGN_CENTER, VALIGN_TOP,
"Favorites");
draw_favorites(menu, display); draw_favorites(menu, display);
if(selected_favorite != -1) { if(selected_item != -1) {
ui_components_actions_bar_text_draw( ui_components_actions_bar_text_draw(
ALIGN_LEFT, VALIGN_TOP, ALIGN_LEFT, VALIGN_TOP,
"A: Load Favorite\n" "A: Load Game"
"B: Exit"
); );
if(screen_mode == BOOKKEEPING_SCREEN_MODE_FAVORITE) {
ui_components_actions_bar_text_draw( ui_components_actions_bar_text_draw(
ALIGN_RIGHT, VALIGN_TOP, ALIGN_RIGHT, VALIGN_TOP,
"R: Remove Favorite" "R: Remove Favorite"
); );
} else {
ui_components_actions_bar_text_draw(
ALIGN_LEFT, VALIGN_TOP,
"\n"
"B: Exit"
);
} }
}
rdpq_detach_show(); rdpq_detach_show();
} }
@ -140,10 +170,29 @@ static void draw(menu_t *menu, surface_t *display) {
void view_favorite_init (menu_t *menu) { void view_favorite_init (menu_t *menu) {
favorite_reset_selected(menu); screen_mode = BOOKKEEPING_SCREEN_MODE_FAVORITE;
item_list = menu->history.favorite_items;
item_max = FAVORITES_COUNT;
reset_selected(menu);
} }
void view_favorite_display (menu_t *menu, surface_t *display) { void view_favorite_display (menu_t *menu, surface_t *display) {
process(menu); process(menu);
draw(menu, display); draw(menu, display);
} }
void view_history_init (menu_t *menu) {
screen_mode = BOOKKEEPING_SCREEN_MODE_HISTORY;
item_list = menu->history.history_items;
item_max = HISTORY_COUNT;
reset_selected(menu);
}
void view_history_display (menu_t *menu, surface_t *display) {
process(menu);
draw(menu, display);
}

View File

@ -40,9 +40,6 @@ static void process (menu_t *menu) {
} else if (menu->actions.back) { } else if (menu->actions.back) {
sound_play_effect(SFX_EXIT); sound_play_effect(SFX_EXIT);
menu->next_mode = MENU_MODE_BROWSER; menu->next_mode = MENU_MODE_BROWSER;
} else if (menu->actions.favorite) {
history_favorite_add(&menu->history, menu->load.rom_path, menu->load.disk_path);
sound_play_effect(SFX_SETTING);
} }
} }
@ -142,7 +139,7 @@ static void load (menu_t *menu) {
return; return;
} }
history_last_rom_set(&menu->history, menu->load.disk_path, menu->load.rom_path); bookkeeping_history_add(&menu->history, menu->load.disk_path, menu->load.rom_path, HISTORY_TYPE_DISK);
menu->next_mode = MENU_MODE_BOOT; menu->next_mode = MENU_MODE_BOOT;
if (load_disk_with_rom) { if (load_disk_with_rom) {
@ -196,24 +193,29 @@ void view_load_disk_init (menu_t *menu) {
menu->boot_pending.disk_file = false; menu->boot_pending.disk_file = false;
if(menu->load.load_last) { if(menu->load.load_history != -1 || menu->load.load_favorite != -1) {
menu->load.disk_path = path_clone(menu->history.last_disk); int id = -1;
bookkeeping_item_t* items;
if(!load_rom(menu, menu->history.last_rom)) { if(menu->load.load_history != -1) {
return; id = menu->load.load_history;
} items = menu->history.history_items;
} else if (menu->load.load_favorite != -1) { } else if (menu->load.load_favorite != -1) {
menu->load.disk_path = path_clone(menu->history.favorites_disk[menu->load.load_favorite]); id = menu->load.load_favorite;
items = menu->history.favorite_items;
}
if(!load_rom(menu, menu->history.favorites_rom[menu->load.load_favorite])) { menu->load.disk_path = path_clone(items[id].primary_path);
if(!load_rom(menu, items[id].secondary_path)) {
return; return;
} }
} else { } else {
menu->load.disk_path = path_clone_push(menu->browser.directory, menu->browser.entry->name); menu->load.disk_path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
} }
menu->load.load_favorite = -1; menu->load.load_favorite = -1;
menu->load.load_last = false; menu->load.load_history = -1;
name = path_last_get(menu->load.disk_path); name = path_last_get(menu->load.disk_path);
disk_err_t err = disk_info_load(menu->load.disk_path, &menu->load.disk_info); disk_err_t err = disk_info_load(menu->load.disk_path, &menu->load.disk_info);

View File

@ -159,7 +159,7 @@ static void set_autoload_type (menu_t *menu, void *arg) {
} }
static void add_favorite (menu_t *menu, void *arg) { static void add_favorite (menu_t *menu, void *arg) {
history_favorite_add(&menu->history, menu->load.rom_path, NULL); bookkeeping_favorite_add(&menu->history, menu->load.rom_path, NULL, HISTORY_TYPE_ROM);
} }
static component_context_menu_t set_cic_type_context_menu = { .list = { static component_context_menu_t set_cic_type_context_menu = { .list = {
@ -341,7 +341,7 @@ static void load (menu_t *menu) {
return; return;
} }
history_last_rom_set(&menu->history, NULL, menu->load.rom_path); bookkeeping_history_add(&menu->history, menu->load.rom_path, NULL, HISTORY_TYPE_ROM);
menu->next_mode = MENU_MODE_BOOT; menu->next_mode = MENU_MODE_BOOT;
@ -368,10 +368,10 @@ void view_load_rom_init (menu_t *menu) {
path_free(menu->load.rom_path); path_free(menu->load.rom_path);
} }
if(menu->load.load_last) { if(menu->load.load_history != -1) {
menu->load.rom_path = path_clone(menu->history.last_rom); menu->load.rom_path = path_clone(menu->history.history_items[menu->load.load_history].primary_path);
} else if(menu->load.load_favorite != -1) { } else if(menu->load.load_favorite != -1) {
menu->load.rom_path = path_clone(menu->history.favorites_rom[menu->load.load_favorite]); menu->load.rom_path = path_clone(menu->history.favorite_items[menu->load.load_history].primary_path);
} else { } else {
menu->load.rom_path = path_clone_push(menu->browser.directory, menu->browser.entry->name); menu->load.rom_path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
} }
@ -380,7 +380,7 @@ void view_load_rom_init (menu_t *menu) {
} }
menu->load.load_favorite = -1; menu->load.load_favorite = -1;
menu->load.load_last = false; menu->load.load_history = -1;
rom_err_t err = rom_info_load(menu->load.rom_path, &menu->load.rom_info); rom_err_t err = rom_info_load(menu->load.rom_path, &menu->load.rom_info);
if (err != ROM_OK) { if (err != ROM_OK) {

View File

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