From e465e241b8a88300b7b8527510d6b643dac10b70 Mon Sep 17 00:00:00 2001 From: Nathaniel Walizer Date: Sun, 11 May 2025 22:39:16 -0700 Subject: [PATCH] Add modal popup support --- Makefile | 2 +- src/linux/port.c | 25 +++++++++++++++---------- src/menu.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/menu.h | 20 ++++++++++++++++++++ src/port.h | 5 +++-- 5 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 src/menu.c create mode 100644 src/menu.h diff --git a/Makefile b/Makefile index c1f5ceb..138723a 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ NESE_SRC_SRCS = f6502.c f6502_opcodes.c NESE_SRC_SRCS += nese.c nes.c cart.c mapper.c NESE_SRC_SRCS += ppu.c apu.c NESE_SRC_SRCS += memory.c serdes.c save.c rle.c -NESE_SRC_SRCS += cartinfo.c +NESE_SRC_SRCS += cartinfo.c menu.c NESE_SRC_SRCS += $(OS)/port.c NESE_GFX_SRCS = $(notdir $(wildcard $(GFXDIR)/*.c)) NESE_MAP_SRCS = $(notdir $(wildcard $(MAPDIR)/*.c)) diff --git a/src/linux/port.c b/src/linux/port.c index 78626fc..355fb0a 100644 --- a/src/linux/port.c +++ b/src/linux/port.c @@ -15,6 +15,7 @@ #include "save.h" #include "draw.h" #include "cartinfo.h" +#include "menu.h" #define NESE_DEBUG "Port" #include "log.h" @@ -98,11 +99,6 @@ typedef struct { /* Input */ -int nese_update_input(void* plat_data, nes_Input* input) { - // Gamepad states are already updated in nese_frame_ready() - return 0; -} - static const int sdl_action_keycodes[Action_Max] = { [Action_Menu] = SDLK_ESCAPE, [Action_Reset] = SDLK_BACKSPACE, @@ -179,6 +175,13 @@ static nese_Action process_events(nes* sys) { return action; } +nese_Action nese_update_input(void* plat_data, nes_Input* input) { + platform_data* plat = (platform_data*)plat_data; + nese_Action action = process_events(plat->sys); + if (NULL != input) *input = plat->sys->core.memory.input; + return action; +} + /* * Time / Video - Should be maximally reusable across platforms @@ -353,8 +356,9 @@ int nese_frame_ready(void* plat_data) { /* Drawing */ -void nese_draw_begin(void* plat_data, int dim) { - draw_begin(&((platform_data*)plat_data)->renderer, dim); +void nese_draw_begin(void* plat_data) { + platform_data* plat = (platform_data*)plat_data; + draw_begin(&plat->renderer, NULL != plat->cart.filename); } void nese_draw_text(void* plat_data, const char* str, int x, int y, uint32_t c) { @@ -422,14 +426,15 @@ int main(int argc, char* argv[]) { if (0 == status) { if (argc <= 1) { - LOGI("No ROM file provided."); + modal_popup(&plat, "No ROM file provided.", color_error); status = -1; } else { status = load_cart(&plat.cart, argv[1], &sys); if (0 != status) { - LOGE("Failed to load %s", argv[1]); - // TODO: Error modal on load failure + char message[128]; + snprintf(message, sizeof(message), "Failed to load %s", argv[1]); + modal_popup(&plat, message, color_error); } } diff --git a/src/menu.c b/src/menu.c new file mode 100644 index 0000000..5767cdc --- /dev/null +++ b/src/menu.c @@ -0,0 +1,47 @@ +#include "menu.h" +#include "nes.h" +#include "action.h" +#include "port.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) { + // TODO: Sleep + uint8_t buttons = input.gamepads[0].buttons; + action = nese_update_input(plat, &input); + changed = (~buttons & input.gamepads[0].buttons); + } + + if (NULL != new_buttons) *new_buttons = input.gamepads[0].buttons; + + return action; +} + + +int 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; +} diff --git a/src/menu.h b/src/menu.h new file mode 100644 index 0000000..d2be6d7 --- /dev/null +++ b/src/menu.h @@ -0,0 +1,20 @@ +#ifndef NESE_MENU_H_ +#define NESE_MENU_H_ + +#include "cartinfo.h" + + +typedef struct { + int cursor; + int top; +} Menu_State; + + +int run_rom_menu(void*, Menu_State*, const Cart_Info*, char* file, int sz_file); + +int run_game_menu(void*, Menu_State*); + +int modal_popup(void*, const char* message, uint32_t color); + + +#endif // NESE_MENU_H_ diff --git a/src/port.h b/src/port.h index 1abd841..9ed0d42 100644 --- a/src/port.h +++ b/src/port.h @@ -4,6 +4,7 @@ #include #include "input.h" +#include "action.h" int nese_file_size(FILE* file); @@ -23,7 +24,7 @@ int nese_frame_start(void*, uint8_t background); int nese_line_ready(void*, uint8_t* buffer, int line); int nese_frame_ready(void*); -int nese_update_input(void*, nes_Input*); +nese_Action nese_update_input(void*, nes_Input*); int nese_get_audio_frequency(void*); @@ -33,7 +34,7 @@ void* nese_alloc_cpu(int); void* nese_alloc(int); -void nese_draw_begin(void*, int dim); +void nese_draw_begin(void*); void nese_draw_text(void*, const char*, int x, int y, uint32_t color); void nese_text_size(void*, const char*, int* w, int* h); void nese_draw_finish(void*);