mirror of
https://github.com/Polprzewodnikowy/N64FlashcartMenu.git
synced 2024-11-28 13:34:14 +01:00
Added 30 FPS frame limiter, file list component fix, cleaned up view display/init code
This commit is contained in:
parent
5d8ebf9200
commit
57dff16ec7
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -34,7 +34,7 @@ jobs:
|
||||
runCmd: |
|
||||
make all -j
|
||||
env:
|
||||
FLAGS: -DMENU_RELEASE
|
||||
FLAGS: -DNDEBUG
|
||||
|
||||
- name: Upload artifact (Standard ROM)
|
||||
uses: actions/upload-artifact@v3
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e37421e8e392e51470bb9dc6b5cd7a7419eeb10c
|
||||
Subproject commit e3b756ecdac6200ff8b6ed255d8f9959137fd325
|
@ -38,12 +38,19 @@ static flashcart_t *flashcart = &((flashcart_t) {
|
||||
.set_save_writeback = NULL,
|
||||
});
|
||||
|
||||
#ifdef NDEBUG
|
||||
// HACK: libdragon mocks every debug function if NDEBUG flag is enabled.
|
||||
// Code below reverts that and point to real function instead.
|
||||
#undef debug_init_sdfs
|
||||
bool debug_init_sdfs (const char *prefix, int npart);
|
||||
#endif
|
||||
|
||||
|
||||
flashcart_error_t flashcart_init (void) {
|
||||
bool sd_initialized;
|
||||
flashcart_error_t error;
|
||||
|
||||
#ifndef MENU_RELEASE
|
||||
#ifndef NDEBUG
|
||||
// NOTE: Some flashcarts doesn't have USB port, can't throw error here
|
||||
debug_init_usblog();
|
||||
#endif
|
||||
@ -116,6 +123,7 @@ flashcart_error_t flashcart_load_file (char *file_path, uint32_t start_offset_ad
|
||||
if ((file_path == NULL) || (!file_exists(file_path))) {
|
||||
return FLASHCART_ERROR_ARGS;
|
||||
}
|
||||
|
||||
return flashcart->load_file(file_path, start_offset_address);
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,7 @@
|
||||
#include "actions.h"
|
||||
|
||||
|
||||
#define ACTIONS_REPEAT_DELAY 16
|
||||
#define ACTIONS_REPEAT_RATE 2
|
||||
#define ACTIONS_REPEAT_DELAY 10
|
||||
#define JOYSTICK_DEADZONE 32
|
||||
|
||||
|
||||
@ -49,7 +48,7 @@ void actions_update (menu_t *menu) {
|
||||
}
|
||||
} else if (held.c[0].up || held.c[0].C_up) {
|
||||
menu->actions.vertical_held_counter += 1;
|
||||
if ((menu->actions.vertical_held_counter >= ACTIONS_REPEAT_DELAY) && (menu->actions.vertical_held_counter % ACTIONS_REPEAT_RATE)) {
|
||||
if (menu->actions.vertical_held_counter >= ACTIONS_REPEAT_DELAY) {
|
||||
menu->actions.go_up = true;
|
||||
if (held.c[0].C_up) {
|
||||
menu->actions.fast = true;
|
||||
@ -57,7 +56,7 @@ void actions_update (menu_t *menu) {
|
||||
}
|
||||
} else if (held.c[0].down || held.c[0].C_down) {
|
||||
menu->actions.vertical_held_counter += 1;
|
||||
if ((menu->actions.vertical_held_counter >= ACTIONS_REPEAT_DELAY) && (menu->actions.vertical_held_counter % ACTIONS_REPEAT_RATE)) {
|
||||
if (menu->actions.vertical_held_counter >= ACTIONS_REPEAT_DELAY) {
|
||||
menu->actions.go_down = true;
|
||||
if (held.c[0].C_down) {
|
||||
menu->actions.fast = true;
|
||||
@ -65,7 +64,7 @@ void actions_update (menu_t *menu) {
|
||||
}
|
||||
} else if (pressed.c[0].y > +JOYSTICK_DEADZONE) { // TODO: requires improvement for responsiveness
|
||||
menu->actions.vertical_held_counter += 1;
|
||||
if ((menu->actions.vertical_held_counter >= ACTIONS_REPEAT_DELAY / 2) && (menu->actions.vertical_held_counter % ACTIONS_REPEAT_RATE)) {
|
||||
if (menu->actions.vertical_held_counter >= ACTIONS_REPEAT_DELAY / 2) {
|
||||
menu->actions.go_up = true;
|
||||
if (pressed.c[0].y < +75) {
|
||||
menu->actions.vertical_held_counter = 0;
|
||||
@ -73,7 +72,7 @@ void actions_update (menu_t *menu) {
|
||||
}
|
||||
} else if (pressed.c[0].y < -JOYSTICK_DEADZONE) { // TODO: requires improvement for responsiveness
|
||||
menu->actions.vertical_held_counter += 1;
|
||||
if ((menu->actions.vertical_held_counter >= ACTIONS_REPEAT_DELAY / 2) && (menu->actions.vertical_held_counter % ACTIONS_REPEAT_RATE)) {
|
||||
if (menu->actions.vertical_held_counter >= ACTIONS_REPEAT_DELAY / 2) {
|
||||
menu->actions.go_down = true;
|
||||
if (pressed.c[0].y > -75) {
|
||||
menu->actions.vertical_held_counter = 0;
|
||||
@ -89,12 +88,12 @@ void actions_update (menu_t *menu) {
|
||||
menu->actions.horizontal_held_counter = 0;
|
||||
} else if (held.c[0].left) {
|
||||
menu->actions.horizontal_held_counter += 1;
|
||||
if ((menu->actions.horizontal_held_counter >= ACTIONS_REPEAT_DELAY) && (menu->actions.horizontal_held_counter % ACTIONS_REPEAT_RATE)) {
|
||||
if (menu->actions.horizontal_held_counter >= ACTIONS_REPEAT_DELAY) {
|
||||
menu->actions.go_left = true;
|
||||
}
|
||||
} else if (held.c[0].right) {
|
||||
menu->actions.horizontal_held_counter += 1;
|
||||
if ((menu->actions.horizontal_held_counter >= ACTIONS_REPEAT_DELAY) && (menu->actions.horizontal_held_counter % ACTIONS_REPEAT_RATE)) {
|
||||
if (menu->actions.horizontal_held_counter >= ACTIONS_REPEAT_DELAY) {
|
||||
menu->actions.go_right = true;
|
||||
}
|
||||
}
|
||||
|
@ -8,15 +8,15 @@
|
||||
static const char *dir_prefix = "/";
|
||||
|
||||
|
||||
static void format_file_size (char *buffer, int size) {
|
||||
static int format_file_size (char *buffer, int size) {
|
||||
if (size < 8 * 1024) {
|
||||
sprintf(buffer, "%d B", size);
|
||||
return sprintf(buffer, "%d B", size);
|
||||
} else if (size < 8 * 1024 * 1024) {
|
||||
sprintf(buffer, "%d kB", size / 1024);
|
||||
return sprintf(buffer, "%d kB", size / 1024);
|
||||
} else if (size < 1 * 1024 * 1024 * 1024) {
|
||||
sprintf(buffer, "%d MB", size / 1024 / 1024);
|
||||
return sprintf(buffer, "%d MB", size / 1024 / 1024);
|
||||
} else {
|
||||
sprintf(buffer, "%d GB", size / 1024 / 1024 / 1024);
|
||||
return sprintf(buffer, "%d GB", size / 1024 / 1024 / 1024);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,11 +40,27 @@ void component_file_list_draw (entry_t *list, int entries, int selected) {
|
||||
STL_UNKNOWN
|
||||
);
|
||||
} else {
|
||||
const int list_max_characters = (256 + strlen(dir_prefix)) * FILE_LIST_ENTRIES;
|
||||
const int paragraph_size = sizeof(rdpq_paragraph_t) + sizeof(rdpq_paragraph_char_t) * list_max_characters;
|
||||
rdpq_paragraph_t *file_list_layout;
|
||||
rdpq_paragraph_t *layout;
|
||||
|
||||
rdpq_paragraph_t *paragraph = calloc(1, paragraph_size);
|
||||
paragraph->capacity = list_max_characters;
|
||||
size_t name_lengths[FILE_LIST_ENTRIES];
|
||||
size_t total_length = 1;
|
||||
|
||||
for (int i = 0; i < FILE_LIST_ENTRIES; i++) {
|
||||
int entry_index = starting_position + i;
|
||||
|
||||
if (entry_index >= entries) {
|
||||
name_lengths[i] = 0;
|
||||
} else {
|
||||
size_t length = strlen(list[entry_index].name);
|
||||
name_lengths[i] = length;
|
||||
total_length += length + (list[entry_index].type == ENTRY_TYPE_DIR ? strlen(dir_prefix) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
file_list_layout = malloc(sizeof(rdpq_paragraph_t) + (sizeof(rdpq_paragraph_char_t) * total_length));
|
||||
memset(file_list_layout, 0, sizeof(rdpq_paragraph_t));
|
||||
file_list_layout->capacity = total_length;
|
||||
|
||||
rdpq_paragraph_builder_begin(
|
||||
&(rdpq_textparms_t) {
|
||||
@ -53,15 +69,13 @@ void component_file_list_draw (entry_t *list, int entries, int selected) {
|
||||
.wrap = WRAP_ELLIPSES,
|
||||
},
|
||||
FNT_DEFAULT,
|
||||
paragraph
|
||||
file_list_layout
|
||||
);
|
||||
|
||||
for (int i = starting_position; i < entries; i++) {
|
||||
if (i == (starting_position + FILE_LIST_ENTRIES)) {
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < FILE_LIST_ENTRIES; i++) {
|
||||
int entry_index = starting_position + i;
|
||||
|
||||
entry_t *entry = &list[i];
|
||||
entry_t *entry = &list[entry_index];
|
||||
|
||||
menu_font_style_t style;
|
||||
|
||||
@ -80,14 +94,18 @@ void component_file_list_draw (entry_t *list, int entries, int selected) {
|
||||
rdpq_paragraph_builder_span(dir_prefix, strlen(dir_prefix));
|
||||
}
|
||||
|
||||
rdpq_paragraph_builder_span(entry->name, strlen(entry->name));
|
||||
rdpq_paragraph_builder_span(entry->name, name_lengths[i]);
|
||||
|
||||
if ((entry_index + 1) >= entries) {
|
||||
break;
|
||||
}
|
||||
|
||||
rdpq_paragraph_builder_newline();
|
||||
}
|
||||
|
||||
rdpq_paragraph_builder_end();
|
||||
layout = rdpq_paragraph_builder_end();
|
||||
|
||||
int highlight_height = (paragraph->bbox[3] - paragraph->bbox[1]) / paragraph->nlines;
|
||||
int highlight_height = (layout->bbox[3] - layout->bbox[1]) / layout->nlines;
|
||||
int highlight_y = VISIBLE_AREA_Y0 + TEXT_MARGIN_VERTICAL + ((selected - starting_position) * highlight_height);
|
||||
|
||||
component_box_draw(
|
||||
@ -99,12 +117,12 @@ void component_file_list_draw (entry_t *list, int entries, int selected) {
|
||||
);
|
||||
|
||||
rdpq_paragraph_render(
|
||||
paragraph,
|
||||
layout,
|
||||
VISIBLE_AREA_X0 + TEXT_MARGIN_HORIZONTAL,
|
||||
VISIBLE_AREA_Y0 + TEXT_MARGIN_VERTICAL
|
||||
);
|
||||
|
||||
memset(paragraph, 0, paragraph_size);
|
||||
rdpq_paragraph_free(layout);
|
||||
|
||||
rdpq_paragraph_builder_begin(
|
||||
&(rdpq_textparms_t) {
|
||||
@ -114,32 +132,33 @@ void component_file_list_draw (entry_t *list, int entries, int selected) {
|
||||
.wrap = WRAP_ELLIPSES,
|
||||
},
|
||||
FNT_DEFAULT,
|
||||
paragraph
|
||||
NULL
|
||||
);
|
||||
|
||||
char file_size[16];
|
||||
char file_size[8];
|
||||
|
||||
for (int i = starting_position; i < entries; i++) {
|
||||
if (i == (starting_position + FILE_LIST_ENTRIES)) {
|
||||
break;
|
||||
}
|
||||
|
||||
entry_t *entry = &list[i];
|
||||
|
||||
if (entry->type != ENTRY_TYPE_DIR) {
|
||||
format_file_size(file_size, entry->size);
|
||||
rdpq_paragraph_builder_span(file_size, strlen(file_size));
|
||||
rdpq_paragraph_builder_span(file_size, format_file_size(file_size, entry->size));
|
||||
}
|
||||
|
||||
if ((i + 1) == (starting_position + FILE_LIST_ENTRIES)) {
|
||||
break;
|
||||
}
|
||||
|
||||
rdpq_paragraph_builder_newline();
|
||||
}
|
||||
|
||||
layout = rdpq_paragraph_builder_end();
|
||||
|
||||
rdpq_paragraph_render(
|
||||
paragraph,
|
||||
layout,
|
||||
VISIBLE_AREA_X0 + TEXT_MARGIN_HORIZONTAL,
|
||||
VISIBLE_AREA_Y0 + TEXT_MARGIN_VERTICAL
|
||||
);
|
||||
|
||||
rdpq_paragraph_free(paragraph);
|
||||
rdpq_paragraph_free(layout);
|
||||
}
|
||||
}
|
||||
|
140
src/menu/menu.c
140
src/menu/menu.c
@ -24,8 +24,17 @@
|
||||
static menu_t *menu;
|
||||
static bool boot_pending;
|
||||
static tv_type_t tv_type;
|
||||
static volatile int frame_counter = 0;
|
||||
|
||||
|
||||
static void frame_counter_handler (void) {
|
||||
frame_counter += 1;
|
||||
}
|
||||
|
||||
static void frame_counter_reset (void) {
|
||||
frame_counter = 0;
|
||||
}
|
||||
|
||||
static void menu_init (boot_params_t *boot_params) {
|
||||
controller_init();
|
||||
timer_init();
|
||||
@ -74,6 +83,8 @@ static void menu_init (boot_params_t *boot_params) {
|
||||
}
|
||||
|
||||
display_init(RESOLUTION_640x480, DEPTH_16_BPP, 2, GAMMA_NONE, ANTIALIAS_OFF);
|
||||
|
||||
register_VI_handler(frame_counter_handler);
|
||||
}
|
||||
|
||||
static void menu_deinit (menu_t *menu) {
|
||||
@ -94,126 +105,61 @@ static void menu_deinit (menu_t *menu) {
|
||||
rtc_close();
|
||||
timer_close();
|
||||
|
||||
unregister_VI_handler(frame_counter_handler);
|
||||
|
||||
display_close();
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Keep this array in sync with menu_mode_t
|
||||
static struct views_s {
|
||||
void (*init) (menu_t *menu);
|
||||
void (*show) (menu_t *menu, surface_t *display);
|
||||
} views[__MENU_MODE_COUNT] = {
|
||||
{ NULL, NULL }, // MENU_MODE_NONE
|
||||
{ view_startup_init, view_startup_display }, // MENU_MODE_STARTUP
|
||||
{ view_browser_init, view_browser_display }, // MENU_MODE_BROWSER
|
||||
{ view_file_info_init, view_file_info_display }, // MENU_MODE_FILE_INFO
|
||||
{ view_system_info_init, view_system_info_display }, // MENU_MODE_SYSTEM_INFO
|
||||
{ view_image_viewer_init, view_image_viewer_display }, // MENU_MODE_IMAGE_VIEWER
|
||||
{ view_music_player_init, view_music_player_display }, // MENU_MODE_MUSIC_PLAYER
|
||||
{ view_credits_init, view_credits_display }, // MENU_MODE_CREDITS
|
||||
{ view_load_init, view_load_display }, // MENU_MODE_LOAD
|
||||
{ view_load_emulator_init, view_load_emulator_display }, // MENU_MODE_EMULATOR_LOAD
|
||||
{ view_error_init, view_error_display }, // MENU_MODE_ERROR
|
||||
{ view_fault_init, view_fault_display }, // MENU_MODE_FAULT
|
||||
{ NULL, NULL }, // MENU_MODE_BOOT
|
||||
};
|
||||
|
||||
void menu_run (boot_params_t *boot_params) {
|
||||
menu_init(boot_params);
|
||||
|
||||
int audio_buffer_length = audio_get_buffer_length();
|
||||
|
||||
while (!boot_pending && (exception_reset_time() < RESET_TIME_LENGTH)) {
|
||||
surface_t *display = display_try_get();
|
||||
surface_t *display = (frame_counter >= 2) ? display_try_get() : NULL;
|
||||
|
||||
if (display != NULL) {
|
||||
frame_counter_reset();
|
||||
|
||||
actions_update(menu);
|
||||
|
||||
switch (menu->mode) {
|
||||
case MENU_MODE_STARTUP:
|
||||
view_startup_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_BROWSER:
|
||||
view_browser_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_FILE_INFO:
|
||||
view_file_info_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_SYSTEM_INFO:
|
||||
view_system_info_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_IMAGE_VIEWER:
|
||||
view_image_viewer_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_MUSIC_PLAYER:
|
||||
view_music_player_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_CREDITS:
|
||||
view_credits_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_LOAD:
|
||||
view_load_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_EMULATOR_LOAD:
|
||||
view_load_emulator_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_ERROR:
|
||||
view_error_display(menu, display);
|
||||
break;
|
||||
|
||||
case MENU_MODE_FAULT:
|
||||
view_fault_display(menu, display);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (views[menu->mode].show) {
|
||||
views[menu->mode].show(menu, display);
|
||||
} else {
|
||||
rdpq_attach_clear(display, NULL);
|
||||
rdpq_detach_show();
|
||||
break;
|
||||
}
|
||||
|
||||
while (menu->mode != menu->next_mode) {
|
||||
menu->mode = menu->next_mode;
|
||||
|
||||
switch (menu->next_mode) {
|
||||
case MENU_MODE_STARTUP:
|
||||
view_startup_init(menu);
|
||||
break;
|
||||
if (views[menu->mode].init) {
|
||||
views[menu->mode].init(menu);
|
||||
}
|
||||
|
||||
case MENU_MODE_BROWSER:
|
||||
view_browser_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_FILE_INFO:
|
||||
view_file_info_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_SYSTEM_INFO:
|
||||
view_system_info_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_IMAGE_VIEWER:
|
||||
view_image_viewer_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_MUSIC_PLAYER:
|
||||
view_music_player_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_CREDITS:
|
||||
view_credits_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_LOAD:
|
||||
view_load_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_EMULATOR_LOAD:
|
||||
view_load_emulator_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_ERROR:
|
||||
view_error_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_FAULT:
|
||||
view_fault_init(menu);
|
||||
break;
|
||||
|
||||
case MENU_MODE_BOOT:
|
||||
if (menu->mode == MENU_MODE_BOOT) {
|
||||
boot_pending = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ typedef enum {
|
||||
MENU_MODE_ERROR,
|
||||
MENU_MODE_FAULT,
|
||||
MENU_MODE_BOOT,
|
||||
__MENU_MODE_COUNT,
|
||||
} menu_mode_t;
|
||||
|
||||
/** @brief File entry type enumeration */
|
||||
|
@ -67,6 +67,7 @@ static void draw (menu_t *menu, surface_t *d) {
|
||||
|
||||
component_actions_bar_text_draw(
|
||||
ALIGN_LEFT, VALIGN_TOP,
|
||||
"\n"
|
||||
"B: Exit"
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user