|
- #include "menu.h"
- #include "nes.h"
- #include "action.h"
- #include "port.h"
- #include "draw.h"
-
-
- static nese_Action wait_for_input(void* plat, uint8_t* new_buttons) {
- nes_Input input = {0};
- nese_Action action = nese_update_input(plat, &input);
- uint8_t changed = 0;
-
- while (0 == changed && Action_OK == action) {
- uint8_t buttons = input.gamepads[0].buttons;
- // Sleep is implicit in nese_update_input
- action = nese_update_input(plat, &input);
- changed = (~buttons & input.gamepads[0].buttons);
- }
-
- if (NULL != new_buttons) *new_buttons = input.gamepads[0].buttons;
-
- return action;
- }
-
- static nese_Action wait_for_input_quiet(void* plat) {
- nes_Input input = {0};
- nese_Action action = nese_update_input(plat, &input);
- uint8_t buttons = input.gamepads[0].buttons;
-
- while (Action_Quit != action && buttons) {
- action = nese_update_input(plat, &input);
- buttons = input.gamepads[0].buttons;
- }
-
- return action;
- }
-
-
- nese_Action modal_popup(void* plat, const char* message, uint32_t color) {
- int w = 0;
- int h = 0;
-
- nese_text_size(plat, message, &w, &h);
-
- int x = ((int)nes_ppu_render_w - w) / 2;
- int y = ((int)nes_ppu_render_h - h) / 2;
-
- if (x < 5) x = 5;
- if (y < 5) y = 5;
-
- nese_Action action = 0;
- uint8_t buttons = 0;
- while (0 == action && 0 == buttons) {
- nese_draw_begin(plat);
- nese_draw_text(plat, message, x, y, color);
- nese_draw_finish(plat);
- action = wait_for_input(plat, &buttons);
- }
-
- return action;
- }
-
- static void fix_filename(char* dst, int n, const char* src) {
- for ( int i = 0;
- i < n && *src && '.' != *src;
- ++i, ++dst, ++src) {
- *dst = ('_' == *src ? ' ' : *src);
- }
- *dst = '\0';
- }
-
- static inline int n_visible(void) {
- return ((nes_ppu_render_h - 20) / 11);
- }
-
- static const uint32_t menu_colors[6] = {
- color_red, color_orange, color_yellow,
- color_green, color_blue, color_purple,
- };
-
- static void show_menu(void* plat, const Menu_State* menu,
- const File_List* files, int x) {
- nese_draw_begin(plat);
-
- int bottom = menu->top + n_visible() - 1;
-
- int max = n_visible();
- if (max > files->count) max = files->count;
- int y = (nes_ppu_render_h - (max * 11)) / 2;
-
- for ( int n = menu->top;
- n < files->count && n <= bottom;
- ++n, y += 11 ) {
- char filename[100];
- fix_filename(filename, sizeof(filename) - 1,
- files->files[n]);
- nese_draw_text(
- plat,
- ( (menu->top == n && 0 != menu->top) ||
- (bottom == n && files->count - 1 > bottom) ) ?
- "..." : filename,
- x, y,
- (menu->cursor == n) ?
- color_white : menu_colors[n % 6]
- );
- if (menu->cursor == n) {
- nese_draw_text(plat, ">", x - 10, y, color_white);
- }
- }
-
- nese_draw_finish(plat);
- }
-
- nese_Action run_menu(void* plat, Menu_State* state,
- const File_List* files, int x) {
- Menu_State menu = {0};
- if (NULL != state) {
- menu = *state;
- if (menu.cursor < 0) {
- menu.cursor = 0;
- } else if (menu.cursor >= files->count) {
- menu.cursor = files->count - 1;
- }
- }
-
- nese_Action action = Action_OK;
- while (Action_OK == action) {
- // Scrolling (do this first to ensure menu is valid)
- const int visible = n_visible() - 1;
- menu.top = menu.cursor - (visible / 2);
- if (menu.top <= 0) {
- // We use <= so we don't readjust the top from 0
- menu.top = 0;
- } else if (menu.top + visible >= files->count) {
- menu.top = (files->count - 1) - visible;
- }
-
- show_menu(plat, &menu, files, x);
-
- uint8_t buttons = 0;
- action = wait_for_input(plat, &buttons);
-
- if (Action_Menu == action) {
- action = Action_Cancel;
-
- } else if (Action_OK == action) {
- if (buttons & (1 << Button_B)) {
- action = Action_Cancel;
- break;
-
- } else if (buttons & ( (1 << Button_A) |
- (1 << Button_Start) )) {
- // Select
- break;
-
- } else if (buttons & (1 << Button_Up)) {
- if (menu.cursor > 0) --menu.cursor;
-
- } else if (buttons & ( (1 << Button_Down) |
- (1 << Button_Select) )) {
- if (menu.cursor < (files->count - 1)) {
- ++menu.cursor;
- } else if (buttons & (1 << Button_Select)) {
- // Wrap around on Select
- menu.cursor = 0;
- }
- }
-
- } else if (Action_Quit != action && Action_Cancel != action) {
- // Ignore anything that isn't "Menu", "Cancel" or "Quit"
- action = Action_OK;
- }
- }
-
- if (NULL != state) *state = menu;
-
- wait_for_input_quiet(plat);
-
- return action;
- }
|