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

History develop #168

Draft
wants to merge 13 commits into
base: develop
Choose a base branch
from
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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use the dpad / joystick e.g.

    menu->actions.go_left = false;
    menu->actions.go_right = false;

as already defined?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left, Right on the D-Pad feels more accident prone, I'd personally want something more specific for the user to press like the C buttons.
I still think that left and right on the dpad should be the fast movement.

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"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given this is menu related, and particular reason why you should not just use the current config.ini with a seperate header?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first I felt it was better to have them in their own file out of the way of the config.ini
that way I could load and save as needed.
also makes it easier to wipe in a single go.


#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