From b84939b49a4e6afd6fd0c6e455d8effd5d89b911 Mon Sep 17 00:00:00 2001 From: Philippe Symons Date: Mon, 9 Mar 2026 19:56:32 +0100 Subject: [PATCH] Add debug menu UI when you press L+R in the main menu. It's only the UI yet. It only shows a couple of dummy options right now. --- Dockerfile | 2 +- Makefile | 8 +- include/button_menu.h | 1 + include/custom_malloc.h | 2 +- include/dbg/debug_menu.h | 57 +++++ include/dbg/debug_menu_functions.h | 7 + include/{ => dbg}/debug_mode.h | 0 include/gb_rom_values/base_gb_rom_struct.h | 2 +- include/mystery_gift_builder.h | 2 +- include/select_menu.h | 4 +- include/sprite_data.h | 2 + include/vertical_menu.h | 5 + include/vertical_menu_cursor_handler.h | 24 ++ source/dbg/debug_menu.cpp | 229 ++++++++++++++++++ source/dbg/debug_menu_functions.cpp | 17 ++ source/gameboy_colour.cpp | 2 +- source/main.cpp | 11 +- source/pokemon_party.cpp | 2 +- source/save_data_manager.cpp | 2 +- source/script_var.cpp | 2 +- source/select_menu.cpp | 15 +- source/sprite_data.cpp | 6 +- source/text_engine.cpp | 2 +- source/vertical_menu.cpp | 21 +- source/vertical_menu_cursor_handler.cpp | 31 +++ .../gb_rom_values/base_gb_rom_struct.h | 2 +- .../src/payloads/payload_builder.cpp | 2 +- tools/text_helper/main.py | 4 +- 28 files changed, 433 insertions(+), 31 deletions(-) create mode 100644 include/dbg/debug_menu.h create mode 100644 include/dbg/debug_menu_functions.h rename include/{ => dbg}/debug_mode.h (100%) create mode 100644 include/vertical_menu_cursor_handler.h create mode 100644 source/dbg/debug_menu.cpp create mode 100644 source/dbg/debug_menu_functions.cpp create mode 100644 source/vertical_menu_cursor_handler.cpp diff --git a/Dockerfile b/Dockerfile index 24e4f93..d8fa123 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,4 +9,4 @@ ARG GROUP_ID ENV DEBIAN_FRONTEND="noninteractive" -RUN apt update && apt install -y build-essential python3-pip python3-png && pip install pandas requests openpyxl --break-system-packages +RUN apt update && apt install -y build-essential python3-pip python3-png python3-debugpy && pip install pandas requests openpyxl --break-system-packages diff --git a/Makefile b/Makefile index a68159e..e4df61e 100644 --- a/Makefile +++ b/Makefile @@ -144,15 +144,17 @@ ifneq ($(BUILD),$(notdir $(CURDIR))) export OUTPUT := $(CURDIR)/$(TARGET) +SOURCE_DIRS_RECURSIVE := $(shell find $(SOURCES) -type d) + export VPATH := $(CURDIR)/$(GENERATED_DIR) \ - $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(SOURCE_DIRS_RECURSIVE),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) export DEPSDIR := $(CURDIR)/$(BUILD) -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(sort $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) translated_text.cpp) +CFILES := $(sort $(notdir $(shell find $(SOURCES) -type f -name "*.c"))) +CPPFILES := $(sort $(notdir $(shell find $(SOURCES) -type f -name "*.cpp")) translated_text.cpp) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) diff --git a/include/button_menu.h b/include/button_menu.h index 78b8250..b517660 100644 --- a/include/button_menu.h +++ b/include/button_menu.h @@ -13,6 +13,7 @@ #define BTN_CREDITS 4 #define BTN_OPENING 5 #define BTN_TEXT_DEBUG 6 +#define BTN_DEBUG_MENU 7 #define BUTTON_CANCEL UINT8_MAX diff --git a/include/custom_malloc.h b/include/custom_malloc.h index a279789..67f05d9 100644 --- a/include/custom_malloc.h +++ b/include/custom_malloc.h @@ -1,7 +1,7 @@ #ifndef CUSTOM_MALLOC_H #define CUSTOM_MALLOC_H -#include "debug_mode.h" +#include "dbg/debug_mode.h" #ifdef __cplusplus extern "C" { diff --git a/include/dbg/debug_menu.h b/include/dbg/debug_menu.h new file mode 100644 index 0000000..51e5989 --- /dev/null +++ b/include/dbg/debug_menu.h @@ -0,0 +1,57 @@ +#ifndef _DEBUG_MENU_H +#define _DEBUG_MENU_H + +#include "vertical_menu.h" + +typedef void (*on_execute_callback)(void *context, unsigned user_param); + +/** + * @brief This struct represents the metadata associated to a single option of a single row in the debug menu. + */ +typedef struct option_data +{ + const char *text; + unsigned value; +} option_data; + +/** + * @brief This struct represents a single row in the debug menu. Each row has a label and a set of options. + * + */ +typedef struct debug_menu_row_data +{ + const u16 *charset; + const char *labelText; + struct { + u8 num_options; + const option_data *options; + on_execute_callback on_option_activate; + u8 selected_option_index; + bool should_delete_on_destruct; + } option_section; + /** + * @brief A callback that you can set to execute when the user selects this row and presses the A button. + */ + on_execute_callback on_execute; + unsigned user_param; +} debug_menu_row_data; + +/** + * @brief This class is responsible for rendering and handling input for a single row in the vertical_menu based + * debug menu. + */ +class debug_menu_row_widget : public i_item_widget +{ +public: + debug_menu_row_widget(const debug_menu_row_data &data); + virtual ~debug_menu_row_widget(); + void render_item(text_data_table &text_table, unsigned x, unsigned y, bool is_focused) override; + MenuInputHandleState handle_input() override; +protected: +private: + debug_menu_row_data data_; +}; + +void show_debug_menu(); + +#endif \ No newline at end of file diff --git a/include/dbg/debug_menu_functions.h b/include/dbg/debug_menu_functions.h new file mode 100644 index 0000000..fff444f --- /dev/null +++ b/include/dbg/debug_menu_functions.h @@ -0,0 +1,7 @@ +#ifndef _DEBUG_MENU_FUNCTIONS_H +#define _DEBUG_MENU_FUNCTIONS_H + + +void dbg_menu_print_number(void *context, unsigned user_param); + +#endif \ No newline at end of file diff --git a/include/debug_mode.h b/include/dbg/debug_mode.h similarity index 100% rename from include/debug_mode.h rename to include/dbg/debug_mode.h diff --git a/include/gb_rom_values/base_gb_rom_struct.h b/include/gb_rom_values/base_gb_rom_struct.h index c65a249..7d381d3 100644 --- a/include/gb_rom_values/base_gb_rom_struct.h +++ b/include/gb_rom_values/base_gb_rom_struct.h @@ -4,7 +4,7 @@ #include #if defined(__arm__) -#include "debug_mode.h" +#include "dbg/debug_mode.h" #endif #if PAYLOAD_EXPORT_TEST || !defined(__arm__) diff --git a/include/mystery_gift_builder.h b/include/mystery_gift_builder.h index 42a7ebc..b64015c 100644 --- a/include/mystery_gift_builder.h +++ b/include/mystery_gift_builder.h @@ -3,7 +3,7 @@ #include #include "pokemon_party.h" -#include "debug_mode.h" +#include "dbg/debug_mode.h" #include "save_data_manager.h" #include "script_var.h" #include "pokemon_data.h" diff --git a/include/select_menu.h b/include/select_menu.h index 5445aa1..64822d4 100644 --- a/include/select_menu.h +++ b/include/select_menu.h @@ -2,11 +2,12 @@ #define SELECT_MENU_H #include "vertical_menu.h" +#include "vertical_menu_cursor_handler.h" #define LANG_MENU 1 #define CART_MENU 2 -class Select_Menu : public i_vertical_menu_state_changed_handler, public i_run_cycle_handler +class Select_Menu : public vertical_menu_cursor_handler, public i_run_cycle_handler { public: Select_Menu(bool enable_cancel, u8 nMenu_type, unsigned nStartX, unsigned nStartY); @@ -15,7 +16,6 @@ public: void clear_options(); void set_lang(u8 nLang); - void on_show() override; void on_hide() override; void on_selection_changed(unsigned new_index, unsigned x, unsigned y) override; diff --git a/include/sprite_data.h b/include/sprite_data.h index b94f4ad..3b73d52 100644 --- a/include/sprite_data.h +++ b/include/sprite_data.h @@ -46,6 +46,8 @@ extern OBJ_ATTR *cart_shell; #include "arrows.h" extern OBJ_ATTR *up_arrow; extern OBJ_ATTR *down_arrow; +extern OBJ_ATTR *toggle_arrow_left; +extern OBJ_ATTR *toggle_arrow_right; extern OBJ_ATTR *point_arrow; #include "unique_duel_frame_menu_sprites.h" diff --git a/include/vertical_menu.h b/include/vertical_menu.h index 77c6bc7..4b4ca28 100644 --- a/include/vertical_menu.h +++ b/include/vertical_menu.h @@ -15,6 +15,11 @@ enum class MenuInputHandleState * @brief This value means that the input was handled. */ HANDLED, + /** + * @brief Same as HANDLED, but also indicates that the viewport should be updated. + * degrades to HANDLED after passing through vertical_menu::handle_input() + */ + HANDLED_UPDATE_VIEWPORT, /** * @brief This value means that a choice was made. * This means that if the vertical_menu is running with ::run(), diff --git a/include/vertical_menu_cursor_handler.h b/include/vertical_menu_cursor_handler.h new file mode 100644 index 0000000..b973013 --- /dev/null +++ b/include/vertical_menu_cursor_handler.h @@ -0,0 +1,24 @@ +#ifndef VERTICAL_MENU_CURSOR_HANDLER_H +#define VERTICAL_MENU_CURSOR_HANDLER_H + +#include "vertical_menu.h" + +/** + * @brief This class handles the cursor behavior for a vertical menu. + */ +class vertical_menu_cursor_handler : public i_vertical_menu_state_changed_handler +{ +public: + vertical_menu_cursor_handler(s16 cursor_offset_x, s16 cursor_offset_y); + virtual ~vertical_menu_cursor_handler(); + + void on_show() override; + void on_hide() override; + void on_selection_changed(unsigned new_index, unsigned x, unsigned y) override; +protected: +private: + const s16 cursor_offset_x_; + const s16 cursor_offset_y_; +}; + +#endif \ No newline at end of file diff --git a/source/dbg/debug_menu.cpp b/source/dbg/debug_menu.cpp new file mode 100644 index 0000000..44fb3c2 --- /dev/null +++ b/source/dbg/debug_menu.cpp @@ -0,0 +1,229 @@ +#include "dbg/debug_menu.h" +#include "dbg/debug_menu_functions.h" +#include "pokemon_data.h" +#include "text_engine.h" +#include "sprite_data.h" +#include "background_engine.h" +#include "vertical_menu_cursor_handler.h" + +#include + +static const option_data toggle_options[2] = { + { + .text = "Off", + .value = 0 + }, + { + .text = "On", + .value = 1 + } +}; + +static const option_data custom_options[] = { + { + .text = "One", + .value = 1 + }, + { + .text = "Two", + .value = 2 + }, + { + .text = "Three", + .value = 3 + } +}; + +/** + * @brief This helper function makes it easy to define a multiple choice debug row. + */ +static debug_menu_row_widget define_debug_choice_row(const u16 *charset, const char *labelText, on_execute_callback option_activate_callback, const option_data *options_metadata, u8 num_options, bool should_delete_options, u8 default_option_index) +{ + const debug_menu_row_data row_data = { + .charset = charset, + .labelText = labelText, + .option_section = { + .num_options = num_options, + .options = options_metadata, + .on_option_activate = option_activate_callback, + .selected_option_index = default_option_index, + .should_delete_on_destruct = should_delete_options + }, + .on_execute = nullptr, + .user_param = 0 + }; + return debug_menu_row_widget(row_data); +} + +/** + * @brief This helper function makes it easy to define a toggle row. + */ +static debug_menu_row_widget define_toggle_row(const u16 *charset, const char* labelText, on_execute_callback on_toggle_callback, bool default_value) +{ + return define_debug_choice_row(charset, labelText, on_toggle_callback, toggle_options, 2, false, default_value ? 1 : 0); +} + +/** + * @brief This helper function makes it easy to define a row that executes a function when you select it and press A. + */ +static debug_menu_row_widget define_executable_row(const u16 *charset, const char* labelText, on_execute_callback on_execute, unsigned user_param) +{ + const debug_menu_row_data row_data = { + .charset = charset, + .labelText = labelText, + .option_section = { + .num_options = 0, + .options = nullptr, + .on_option_activate = nullptr, + .selected_option_index = 0, + .should_delete_on_destruct = false + }, + .on_execute = on_execute, + .user_param = user_param + }; + return debug_menu_row_widget(row_data); +} + +void show_debug_menu() +{ + u16 charset[256]; + const s16 cursor_offset_x = 3; + const s16 cursor_offset_y = 6; + + load_localized_charset(charset, 3, ENGLISH); + tte_erase_rect(0, 0, H_MAX, V_MAX); + erase_textbox_tiles(); + show_text_box(); + tte_set_ink(INK_DARK_GREY); + + obj_unhide(toggle_arrow_left, 0); + + debug_menu_row_widget row_widget_default_off = define_toggle_row(charset, "Def_Off", dbg_menu_print_number, false); + debug_menu_row_widget row_widget_default_on = define_toggle_row(charset, "Def_On", dbg_menu_print_number, true); + debug_menu_row_widget row_widget_custom_options = define_debug_choice_row(charset, "Custom", dbg_menu_print_number, custom_options, 3, false, 1); + debug_menu_row_widget row_widget_executable = define_executable_row(charset, "Exec", dbg_menu_print_number, 128); + + const vertical_menu_settings menu_settings = { + .x = 20, + .y = 0, + .width = 200, + .height = 155, + .margin_top = 8, + .margin_bottom = 8, + .initial_focus_index = 0, + .item_height = 10, + .text_table_index = INT32_MAX, + .allow_cancel = true, + .should_delete_item_widgets_on_destruct = false, + .should_hide_state_changed_handler_on_not_focused = true + }; + + vertical_menu_cursor_handler cursor_handler(cursor_offset_x, cursor_offset_y); + vertical_menu debug_menu(menu_settings); + + i_item_widget* item_widgets[] = { + &row_widget_default_off, + &row_widget_default_on, + &row_widget_custom_options, + &row_widget_executable + }; + debug_menu.set_state_changed_handler(&cursor_handler); + debug_menu.add_item_widgets(item_widgets, sizeof(item_widgets) / sizeof(item_widgets[0])); + + debug_menu.show(); + debug_menu.run(); + debug_menu.hide(); + + hide_text_box(); + tte_erase_rect(0, 0, H_MAX, V_MAX); +} + +debug_menu_row_widget::debug_menu_row_widget(const debug_menu_row_data &data) + : data_(data) +{ +} + +debug_menu_row_widget::~debug_menu_row_widget() +{ +} + +void debug_menu_row_widget::render_item(text_data_table &text_table, unsigned x, unsigned y, bool is_focused) +{ + const int label_margin_left = 12; + const int margin_top = 2; + const int option_margin_left = 120; + const int toggle_arrow_left_offset_x = -10; + const int toggle_arrow_right_offset_x = 35; + const int toggle_arrows_offset_y = 4; + + tte_set_pos(x + label_margin_left, y + margin_top); + ptgb_write_debug(data_.charset, data_.labelText, true); + + if(data_.option_section.num_options > 0) + { + const u8 selected_option_index = data_.option_section.selected_option_index; + + tte_set_pos(x + option_margin_left, y + margin_top); + ptgb_write_debug(data_.charset, data_.option_section.options[selected_option_index].text, true); + } + + if(is_focused) + { + if(data_.option_section.num_options > 0) + { + const int toggle_arrow_left_x = static_cast(x) + option_margin_left + toggle_arrow_left_offset_x; + const int toggle_arrow_right_x = static_cast(x) + option_margin_left + toggle_arrow_right_offset_x; + const int toggle_arrows_y = static_cast(y) + margin_top + toggle_arrows_offset_y; + + obj_set_pos(toggle_arrow_left, toggle_arrow_left_x, toggle_arrows_y); + obj_set_pos(toggle_arrow_right, toggle_arrow_right_x, toggle_arrows_y); + obj_unhide(toggle_arrow_left, 0); + obj_unhide(toggle_arrow_right, 0); + } + else + { + obj_hide(toggle_arrow_left); + obj_hide(toggle_arrow_right); + } + } +} + +MenuInputHandleState debug_menu_row_widget::handle_input() +{ + if(data_.option_section.num_options > 0) + { + bool handled = false; + if(key_hit(KEY_RIGHT)) + { + data_.option_section.selected_option_index = (data_.option_section.selected_option_index + 1) % data_.option_section.num_options; + handled = true; + } + if(key_hit(KEY_LEFT)) + { + --data_.option_section.selected_option_index; + if(data_.option_section.selected_option_index >= data_.option_section.num_options) + { + data_.option_section.selected_option_index = data_.option_section.num_options - 1; + } + handled = true; + } + + if(handled && data_.option_section.on_option_activate) + { + data_.option_section.on_option_activate(this, data_.option_section.options[data_.option_section.selected_option_index].value); + } + + if(handled) + { + return MenuInputHandleState::HANDLED_UPDATE_VIEWPORT; + } + } + + if(key_hit(KEY_A) && data_.on_execute) + { + data_.on_execute(this, data_.user_param); + return MenuInputHandleState::HANDLED; + } + + return MenuInputHandleState::NOT_HANDLED; +} \ No newline at end of file diff --git a/source/dbg/debug_menu_functions.cpp b/source/dbg/debug_menu_functions.cpp new file mode 100644 index 0000000..63c92bd --- /dev/null +++ b/source/dbg/debug_menu_functions.cpp @@ -0,0 +1,17 @@ +#include "dbg/debug_menu_functions.h" +#include "libraries/nanoprintf/nanoprintf.h" +#include "text_engine.h" +#include "pokemon_data.h" + +void dbg_menu_print_number(void *context, unsigned user_param) +{ + (void)context; + char buf[64]; + npf_snprintf(buf, sizeof(buf), "%u", user_param); + uint16_t charset[256]; + load_localized_charset(charset, 3, ENGLISH); + + tte_erase_rect(0, 0, 100, 12); + tte_set_pos(0, 0); + ptgb_write_debug(charset, buf, true); +} \ No newline at end of file diff --git a/source/gameboy_colour.cpp b/source/gameboy_colour.cpp index 4db3084..70711e1 100644 --- a/source/gameboy_colour.cpp +++ b/source/gameboy_colour.cpp @@ -9,7 +9,7 @@ #include "gameboy_colour.h" #include "pokemon_trade.h" #include "script_array.h" -#include "debug_mode.h" +#include "dbg/debug_mode.h" #include "interrupt.h" #include "text_engine.h" #include "global_frame_controller.h" diff --git a/source/main.cpp b/source/main.cpp index 3fda236..7682e1c 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -14,7 +14,8 @@ #include "sprite_data.h" #include "button_handler.h" #include "button_menu.h" -#include "debug_mode.h" +#include "dbg/debug_mode.h" +#include "dbg/debug_menu.h" // #include "soundbank.h" // #include "soundbank_bin.h" #include "dex_handler.h" @@ -343,6 +344,10 @@ int main_menu_loop() ptgb_write("#{cx:0xF000}"); return return_values[curr_selection]; } + else if ((key_held(KEY_L) && key_held(KEY_R))) + { + return BTN_DEBUG_MENU; + } else { update = false; @@ -558,6 +563,10 @@ int main(void) obj_hide_multi(ptgb_logo_l, 2); text_loop(SCRIPT_DEBUG); break; + case (BTN_DEBUG_MENU): + obj_hide_multi(ptgb_logo_l, 2); + show_debug_menu(); + break; default: global_next_frame(); } diff --git a/source/pokemon_party.cpp b/source/pokemon_party.cpp index d533b58..c4b7373 100644 --- a/source/pokemon_party.cpp +++ b/source/pokemon_party.cpp @@ -1,7 +1,7 @@ #include "gameboy_colour.h" #include "pokemon_party.h" #include "flash_mem.h" -#include "debug_mode.h" +#include "dbg/debug_mode.h" #include "mystery_gift_injector.h" #include "gb_rom_values/gb_rom_values.h" #include "sprite_data.h" diff --git a/source/save_data_manager.cpp b/source/save_data_manager.cpp index d6c99c3..0d780d7 100644 --- a/source/save_data_manager.cpp +++ b/source/save_data_manager.cpp @@ -1,7 +1,7 @@ #include #include "save_data_manager.h" #include "flash_mem.h" -#include "debug_mode.h" +#include "dbg/debug_mode.h" #include "button_menu.h" #include "pokemon_data.h" #include "libraries/Pokemon-Gen3-to-Gen-X/include/save.h" diff --git a/source/script_var.cpp b/source/script_var.cpp index 9dfbf27..0ec07e9 100644 --- a/source/script_var.cpp +++ b/source/script_var.cpp @@ -2,7 +2,7 @@ #include "libstd_replacements.h" #include "script_var.h" #include "pokemon_data.h" -#include "debug_mode.h" +#include "dbg/debug_mode.h" #include "global_frame_controller.h" extern rom_data curr_GBA_rom; diff --git a/source/select_menu.cpp b/source/select_menu.cpp index 27421e3..a09a00f 100644 --- a/source/select_menu.cpp +++ b/source/select_menu.cpp @@ -10,7 +10,8 @@ #define TILE_WIDTH 8 Select_Menu::Select_Menu(bool enable_cancel, u8 nMenu_type, unsigned nStartTileX, unsigned nStartTileY) - : menu_widget_(vertical_menu_settings{ + : vertical_menu_cursor_handler(TEXT_WIDTH, 3) + , menu_widget_(vertical_menu_settings{ .x = static_cast(nStartTileX * TILE_WIDTH), .y = static_cast(nStartTileY * TILE_HEIGHT), .width = 10 * TEXT_WIDTH, @@ -84,14 +85,10 @@ void Select_Menu::set_lang(u8 nLang) lang = nLang; } -void Select_Menu::on_show() -{ - obj_unhide(point_arrow, 0); -} - void Select_Menu::on_hide() { - obj_hide(point_arrow); + // call the base implementation to hide the cursor + vertical_menu_cursor_handler::on_hide(); obj_hide(cart_shell); obj_hide(cart_label); obj_hide(flag); @@ -99,8 +96,8 @@ void Select_Menu::on_hide() void Select_Menu::on_selection_changed(unsigned new_index, unsigned x, unsigned y) { - // set the cursor accordingly - obj_set_pos(point_arrow, x + TEXT_WIDTH, y + 3); + // call the base implementation to move the cursor + vertical_menu_cursor_handler::on_selection_changed(new_index, x, y); simple_item_renderer* widget = static_cast(menu_widget_.get_item_widget_at(new_index)); const unsigned item_value = (widget) ? widget->get_data().value : UINT8_MAX; diff --git a/source/sprite_data.cpp b/source/sprite_data.cpp index 96faec7..d6ce1f9 100644 --- a/source/sprite_data.cpp +++ b/source/sprite_data.cpp @@ -1,7 +1,7 @@ #include #include #include "sprite_data.h" -#include "debug_mode.h" +#include "dbg/debug_mode.h" #include "gba_rom_values/base_gba_rom_struct.h" #include "global_frame_controller.h" @@ -368,6 +368,8 @@ OBJ_ATTR *type_sprites[14] = { OBJ_ATTR *up_arrow = &obj_buffer[num_sprites++]; OBJ_ATTR *down_arrow = &obj_buffer[num_sprites++]; +OBJ_ATTR *toggle_arrow_left = &obj_buffer[num_sprites++]; +OBJ_ATTR *toggle_arrow_right = &obj_buffer[num_sprites++]; OBJ_ATTR *point_arrow = &obj_buffer[num_sprites++]; OBJ_ATTR *box_select = &obj_buffer[num_sprites++]; @@ -449,6 +451,8 @@ void load_eternal_sprites() unsigned int tempTileBuf[48]; BitUnPack(arrowsTiles, tempTileBuf, arrowsTilesLen, 1, 4); load_sprite(point_arrow, &tempTileBuf[32], 32, curr_tile_id, BTN_PAL, ATTR0_SQUARE, ATTR1_SIZE_8x8, 1); + load_sprite(toggle_arrow_right, &tempTileBuf[40], 32, curr_tile_id, BTN_PAL, ATTR0_SQUARE, ATTR1_SIZE_8x8, 1); + load_sprite(toggle_arrow_left, &tempTileBuf[40], 32, curr_tile_id, BTN_PAL, ATTR0_SQUARE, ATTR1_SIZE_8x8 | ATTR1_HFLIP, 1); load_sprite(down_arrow, &tempTileBuf[0], 64, curr_tile_id, BTN_PAL, ATTR0_WIDE, ATTR1_SIZE_16x8, 1); load_sprite(up_arrow, &tempTileBuf[16], 64, curr_tile_id, BTN_PAL, ATTR0_WIDE, ATTR1_SIZE_16x8, 1); load_sprite_compressed(link_frame1, link_frame1Tiles, curr_tile_id, LINK_CABLE_PAL, ATTR0_SQUARE, ATTR1_SIZE_32x32, 1); diff --git a/source/text_engine.cpp b/source/text_engine.cpp index 65fe827..2d546c6 100644 --- a/source/text_engine.cpp +++ b/source/text_engine.cpp @@ -5,7 +5,7 @@ #include "global_frame_controller.h" #include "pkmn_font.h" #include "script_array.h" -#include "debug_mode.h" +#include "dbg/debug_mode.h" #include "button_menu.h" #include "sprite_data.h" #include "fonts.h" diff --git a/source/vertical_menu.cpp b/source/vertical_menu.cpp index 8d6baa9..22f81f1 100644 --- a/source/vertical_menu.cpp +++ b/source/vertical_menu.cpp @@ -144,6 +144,7 @@ MenuInputHandleState vertical_menu::handle_input() { MenuInputHandleState result; bool did_navigate = false; + bool viewport_updated = false; // If no items or not focused, there's nothing to handle. if(items_.size() <= 1 || !is_focused_) @@ -154,6 +155,14 @@ MenuInputHandleState vertical_menu::handle_input() // the focused item widget gets the first chance to handle input, // since it might have some special behavior for certain keys. result = items_[focused_index_]->handle_input(); + if(result == MenuInputHandleState::HANDLED_UPDATE_VIEWPORT) + { + // the child widget is requesting that we update the viewport. + // so we do that here and then degrade the result to HANDLED, + // since we've already done the viewport update that the child widget requested. + update_viewport(); + result = MenuInputHandleState::HANDLED; // degrade to HANDLED after updating the viewport + } if(result != MenuInputHandleState::NOT_HANDLED) { return result; @@ -173,6 +182,7 @@ MenuInputHandleState vertical_menu::handle_input() if(focused_index_ >= current_viewport_end_index) { ++viewport_start_index_; + viewport_updated = true; } did_navigate = true; } @@ -182,6 +192,7 @@ MenuInputHandleState vertical_menu::handle_input() if(focused_index_ < viewport_start_index_) { --viewport_start_index_; + viewport_updated = true; } did_navigate = true; } @@ -190,7 +201,10 @@ MenuInputHandleState vertical_menu::handle_input() if(did_navigate) { const unsigned render_index = focused_index_ - viewport_start_index_; - update_viewport(); + if(viewport_updated) + { + update_viewport(); + } handle_selection_change(focused_index_, settings_.x, settings_.y + settings_.margin_top + (render_index * settings_.item_height)); return MenuInputHandleState::HANDLED; } @@ -205,7 +219,10 @@ void vertical_menu::update_viewport() clear_viewport(); - text_table.decompress(get_compressed_text_table(settings_.text_table_index)); + if(settings_.text_table_index != INT32_MAX) + { + text_table.decompress(get_compressed_text_table(settings_.text_table_index)); + } const unsigned num_visible_items = get_num_visible_items(settings_.height, settings_.margin_top, settings_.margin_bottom, settings_.item_height); const unsigned viewport_end_index = get_viewport_end_index(viewport_start_index_, num_visible_items, items_.size()); diff --git a/source/vertical_menu_cursor_handler.cpp b/source/vertical_menu_cursor_handler.cpp new file mode 100644 index 0000000..39383d1 --- /dev/null +++ b/source/vertical_menu_cursor_handler.cpp @@ -0,0 +1,31 @@ +#include "vertical_menu_cursor_handler.h" +#include "sprite_data.h" + +vertical_menu_cursor_handler::vertical_menu_cursor_handler(s16 cursor_offset_x, s16 cursor_offset_y) + : cursor_offset_x_(cursor_offset_x) + , cursor_offset_y_(cursor_offset_y) +{ +} + +vertical_menu_cursor_handler::~vertical_menu_cursor_handler() +{ +} + +void vertical_menu_cursor_handler::on_show() +{ + obj_unhide(point_arrow, 0); +} + +void vertical_menu_cursor_handler::on_hide() +{ + obj_hide(point_arrow); +} + +void vertical_menu_cursor_handler::on_selection_changed(unsigned new_index, unsigned x, unsigned y) +{ + // set the cursor pos accordingly + const int cursor_x = static_cast(x) + cursor_offset_x_; + const int cursor_y = static_cast(y) + cursor_offset_y_; + + obj_set_pos(point_arrow, cursor_x, cursor_y); +} \ No newline at end of file diff --git a/tools/payload-generator/include/gb_rom_values/base_gb_rom_struct.h b/tools/payload-generator/include/gb_rom_values/base_gb_rom_struct.h index c65a249..7d381d3 100644 --- a/tools/payload-generator/include/gb_rom_values/base_gb_rom_struct.h +++ b/tools/payload-generator/include/gb_rom_values/base_gb_rom_struct.h @@ -4,7 +4,7 @@ #include #if defined(__arm__) -#include "debug_mode.h" +#include "dbg/debug_mode.h" #endif #if PAYLOAD_EXPORT_TEST || !defined(__arm__) diff --git a/tools/payload-generator/src/payloads/payload_builder.cpp b/tools/payload-generator/src/payloads/payload_builder.cpp index f1ee5c5..1695b1c 100644 --- a/tools/payload-generator/src/payloads/payload_builder.cpp +++ b/tools/payload-generator/src/payloads/payload_builder.cpp @@ -1,7 +1,7 @@ #include "payloads/payload_builder.h" #include "gb_rom_values/base_gb_rom_struct.h" #include "payloads/z80_asm.h" -#include "../../../include/debug_mode.h" +#include "../../../include/dbg/debug_mode.h" #include #define DATA_LOC (SHOW_DATA_PACKETS ? curr_rom.transferStringLocation : curr_rom.wEnemyMonSpecies) diff --git a/tools/text_helper/main.py b/tools/text_helper/main.py index ac3525d..0b25554 100644 --- a/tools/text_helper/main.py +++ b/tools/text_helper/main.py @@ -692,7 +692,7 @@ def generate_text_tables(): def generate_cpp_file(): print("\tGenerating cpp file") with open(TRANSLATED_CPP_PATH, 'w') as cppFile: - cppFile.write("// THIS FILE HAS BEEN GENERATED BY text_helper/main.py !\n#include \"translated_text.h\"\n#include \"debug_mode.h\"\n") + cppFile.write("// THIS FILE HAS BEEN GENERATED BY text_helper/main.py !\n#include \"translated_text.h\"\n#include \"dbg/debug_mode.h\"\n") # generate includes for each language for lang in Languages: for section in textSections: @@ -766,7 +766,7 @@ def build_h(): #error "PTGB_BUILD_LANGUAGE not defined" #endif -#include "debug_mode.h" +#include "dbg/debug_mode.h" #include "pokemon_data.h" #ifndef __FONTS_H__