diff --git a/graphics/arrows.png b/graphics/arrows.png index 7dd645e..47f390b 100644 Binary files a/graphics/arrows.png and b/graphics/arrows.png differ diff --git a/include/dbg/debug_menu.h b/include/dbg/debug_menu.h index ae69289..d84855c 100644 --- a/include/dbg/debug_menu.h +++ b/include/dbg/debug_menu.h @@ -3,7 +3,7 @@ #include "vertical_menu.h" -typedef void (*on_execute_callback)(unsigned user_param); +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. @@ -27,12 +27,13 @@ typedef struct debug_menu_row_data const option_data *options; on_execute_callback on_option_activate; u8 selected_option_index; - bool should_delete_on_destruct; + bool should_free_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; + void *context; unsigned user_param; } debug_menu_row_data; diff --git a/include/dbg/debug_menu_functions.h b/include/dbg/debug_menu_functions.h index bdf0df7..f62840c 100644 --- a/include/dbg/debug_menu_functions.h +++ b/include/dbg/debug_menu_functions.h @@ -1,10 +1,9 @@ #ifndef _DEBUG_MENU_FUNCTIONS_H #define _DEBUG_MENU_FUNCTIONS_H - -void dbg_menu_print_number(unsigned user_param); - -void show_text_debug_screen(unsigned user_param); -void show_debug_info_screen(unsigned user_param); +void show_text_debug_screen(void *context, unsigned user_param); +void show_debug_info_screen(void *context, unsigned user_param); +void dbg_set_boolean_flag(void *context, unsigned user_param); +void dbg_play_song(void *context, unsigned user_param); #endif \ No newline at end of file diff --git a/include/dbg/debug_mode.h b/include/dbg/debug_mode.h index d737908..9e7c163 100644 --- a/include/dbg/debug_mode.h +++ b/include/dbg/debug_mode.h @@ -55,6 +55,7 @@ extern debug_options g_debug_options; // Compile time options #define ENABLE_DEBUG_MENU true +#define ENABLE_TEXT_DEBUG_SCREEN true #define USE_CUSTOM_MALLOC 1 // needs to be a value divisible by 4 #define CUSTOM_MALLOC_POOL_SIZE 8192 diff --git a/source/dbg/debug_menu.cpp b/source/dbg/debug_menu.cpp index cad3906..479ea71 100644 --- a/source/dbg/debug_menu.cpp +++ b/source/dbg/debug_menu.cpp @@ -4,10 +4,13 @@ #include "sprite_data.h" #include "background_engine.h" #include "vertical_menu_cursor_handler.h" +#include "libraries/nanoprintf/nanoprintf.h" #include +#include static on_execute_callback delayed_execute_callback = nullptr; +static void *delayed_execute_context = nullptr; static unsigned delayed_execute_user_param = 0; void show_debug_menu() @@ -57,8 +60,9 @@ void show_debug_menu() // to avoid rendering issues. if(delayed_execute_callback) { - delayed_execute_callback(delayed_execute_user_param); + delayed_execute_callback(delayed_execute_context, delayed_execute_user_param); delayed_execute_callback = nullptr; + delayed_execute_context = nullptr; delayed_execute_user_param = 0; } } @@ -70,6 +74,11 @@ debug_menu_row_widget::debug_menu_row_widget(const debug_menu_row_data &data) debug_menu_row_widget::~debug_menu_row_widget() { + if(data_.option_section.should_free_on_destruct) + { + free(const_cast(data_.option_section.options)); + data_.option_section.options = nullptr; + } } void debug_menu_row_widget::render_item(text_data_table &text_table, unsigned x, unsigned y, bool is_focused) @@ -89,7 +98,16 @@ void debug_menu_row_widget::render_item(text_data_table &text_table, unsigned x, 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(data_.option_section.options[selected_option_index].text) + { + ptgb_write_debug(data_.charset, data_.option_section.options[selected_option_index].text, true); + } + else + { + char buf[32]; + npf_snprintf(buf, sizeof(buf), "%u", data_.option_section.options[selected_option_index].value); + ptgb_write_debug(data_.charset, buf, true); + } } if(is_focused) @@ -135,7 +153,7 @@ MenuInputHandleState debug_menu_row_widget::handle_input() if(handled && data_.option_section.on_option_activate) { - data_.option_section.on_option_activate(data_.option_section.options[data_.option_section.selected_option_index].value); + data_.option_section.on_option_activate(data_.context, data_.option_section.options[data_.option_section.selected_option_index].value); } if(handled) @@ -147,6 +165,7 @@ MenuInputHandleState debug_menu_row_widget::handle_input() if(key_hit(KEY_A) && data_.on_execute) { delayed_execute_callback = data_.on_execute; + delayed_execute_context = data_.context; delayed_execute_user_param = data_.user_param; return MenuInputHandleState::CHOICE_MADE; } diff --git a/source/dbg/debug_menu_entries.cpp b/source/dbg/debug_menu_entries.cpp index d41a268..1a750d0 100644 --- a/source/dbg/debug_menu_entries.cpp +++ b/source/dbg/debug_menu_entries.cpp @@ -1,8 +1,12 @@ #include "dbg/debug_menu.h" #include "dbg/debug_menu_entries.h" #include "dbg/debug_menu_functions.h" +#include "dbg/debug_mode.h" +#include "soundbank.h" #include "vertical_menu.h" +#include + static const option_data toggle_options[2] = { { .text = "Off", @@ -14,25 +18,10 @@ static const option_data toggle_options[2] = { } }; -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) +static debug_menu_row_widget __attribute__((noinline)) 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, void *context) { const debug_menu_row_data row_data = { .charset = charset, @@ -42,9 +31,10 @@ static debug_menu_row_widget define_debug_choice_row(const u16 *charset, const c .options = options_metadata, .on_option_activate = option_activate_callback, .selected_option_index = default_option_index, - .should_delete_on_destruct = should_delete_options + .should_free_on_destruct = should_delete_options }, .on_execute = nullptr, + .context = context, .user_param = 0 }; return debug_menu_row_widget(row_data); @@ -53,15 +43,34 @@ static debug_menu_row_widget define_debug_choice_row(const u16 *charset, const c /** * @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) +static debug_menu_row_widget define_toggle_row(const u16 *charset, const char* labelText, on_execute_callback on_toggle_callback, bool default_value, void *context) { - return define_debug_choice_row(charset, labelText, on_toggle_callback, toggle_options, 2, false, default_value ? 1 : 0); + return define_debug_choice_row(charset, labelText, on_toggle_callback, toggle_options, 2, false, default_value ? 1 : 0, context); +} + +static debug_menu_row_widget __attribute__((noinline)) define_song_row(const u16 *charset, const char* labelText) +{ + option_data *song_options = (option_data*)malloc(sizeof(option_data) * (MSL_NSONGS + 1)); + song_options[0] = { + .text = "None", + .value = UINT32_MAX + }; + + for(unsigned i = 0; i < MSL_NSONGS; ++i) + { + song_options[i + 1] = { + .text = nullptr, + .value = i + }; + } + + return define_debug_choice_row(charset, labelText, dbg_play_song, song_options, MSL_NSONGS + 1, true, 0, nullptr); } /** * @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) +static debug_menu_row_widget __attribute__((noinline)) define_executable_row(const u16 *charset, const char* labelText, on_execute_callback on_execute, unsigned user_param, void *context) { const debug_menu_row_data row_data = { .charset = charset, @@ -71,9 +80,10 @@ static debug_menu_row_widget define_executable_row(const u16 *charset, const cha .options = nullptr, .on_option_activate = nullptr, .selected_option_index = 0, - .should_delete_on_destruct = false + .should_free_on_destruct = false }, .on_execute = on_execute, + .context = context, .user_param = user_param }; return debug_menu_row_widget(row_data); @@ -81,18 +91,44 @@ static debug_menu_row_widget define_executable_row(const u16 *charset, const cha void fill_debug_menu_with_entries(vertical_menu &menu, u16 *charset) { - 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 txt_dbg_screen = define_executable_row(charset, "Text Debug Screen", show_text_debug_screen, 0); - debug_menu_row_widget dbg_info_screen = define_executable_row(charset, "Debug Info Screen", show_debug_info_screen, 0); +#if ENABLE_TEXT_DEBUG_SCREEN + debug_menu_row_widget txt_dbg_screen = define_executable_row(charset, "Text Debug", show_text_debug_screen, 0, nullptr); +#endif + debug_menu_row_widget dbg_info_screen = define_executable_row(charset, "Info", show_debug_info_screen, 0, nullptr); + debug_menu_row_widget row_play_song = define_song_row(charset, "Song"); + debug_menu_row_widget row_print_link_data = define_toggle_row(charset, "Print Link", dbg_set_boolean_flag, g_debug_options.print_link_data, &g_debug_options.print_link_data); + debug_menu_row_widget row_instant_text_speed = define_toggle_row(charset, "Instant Text", dbg_set_boolean_flag, g_debug_options.instant_text_speed, &g_debug_options.instant_text_speed); + debug_menu_row_widget row_ignore_game_pak = define_toggle_row(charset, "Ign Cart", dbg_set_boolean_flag, g_debug_options.ignore_game_pak, &g_debug_options.ignore_game_pak); + debug_menu_row_widget row_ignore_game_pak_sprites = define_toggle_row(charset, "Ign Sprites", dbg_set_boolean_flag, g_debug_options.ignore_game_pak_sprites, &g_debug_options.ignore_game_pak_sprites); + debug_menu_row_widget row_ignore_link_cable = define_toggle_row(charset, "Ign Link", dbg_set_boolean_flag, g_debug_options.ignore_link_cable, &g_debug_options.ignore_link_cable); + debug_menu_row_widget row_ignore_mg_e4_flags = define_toggle_row(charset, "Ign MG/E4", dbg_set_boolean_flag, g_debug_options.ignore_mg_e4_flags, &g_debug_options.ignore_mg_e4_flags); + debug_menu_row_widget row_ignore_unreceived_pkmn = define_toggle_row(charset, "Ign Unrec PKMN", dbg_set_boolean_flag, g_debug_options.ignore_unreceived_pkmn, &g_debug_options.ignore_unreceived_pkmn); + debug_menu_row_widget row_force_tutorial = define_toggle_row(charset, "Force Tut", dbg_set_boolean_flag, g_debug_options.force_tutorial, &g_debug_options.force_tutorial); + debug_menu_row_widget row_dont_hide_invalid_pkmn = define_toggle_row(charset, "Show Invalid", dbg_set_boolean_flag, g_debug_options.dont_hide_invalid_pkmn, &g_debug_options.dont_hide_invalid_pkmn); + debug_menu_row_widget row_ignore_dex_completion = define_toggle_row(charset, "Ign Dex Compl", dbg_set_boolean_flag, g_debug_options.ignore_dex_completion, &g_debug_options.ignore_dex_completion); + debug_menu_row_widget row_force_all_caught = define_toggle_row(charset, "Force Caught", dbg_set_boolean_flag, g_debug_options.force_all_caught, &g_debug_options.force_all_caught); + debug_menu_row_widget row_write_cable_data_to_save = define_toggle_row(charset, "Write Cbl Data", dbg_set_boolean_flag, g_debug_options.write_cable_data_to_save, &g_debug_options.write_cable_data_to_save); + debug_menu_row_widget row_display_control_char = define_toggle_row(charset, "Disp CtrlChr", dbg_set_boolean_flag, g_debug_options.display_control_char, &g_debug_options.display_control_char); i_item_widget* item_widgets[] = { - &row_widget_default_off, - &row_widget_default_on, - &row_widget_custom_options, +#if ENABLE_TEXT_DEBUG_SCREEN &txt_dbg_screen, - &dbg_info_screen +#endif + &dbg_info_screen, + &row_play_song, + &row_print_link_data, + &row_instant_text_speed, + &row_ignore_game_pak, + &row_ignore_game_pak_sprites, + &row_ignore_link_cable, + &row_ignore_mg_e4_flags, + &row_ignore_unreceived_pkmn, + &row_force_tutorial, + &row_dont_hide_invalid_pkmn, + &row_ignore_dex_completion, + &row_force_all_caught, + &row_write_cable_data_to_save, + &row_display_control_char }; menu.add_item_widgets(item_widgets, sizeof(item_widgets) / sizeof(item_widgets[0])); diff --git a/source/dbg/debug_menu_functions.cpp b/source/dbg/debug_menu_functions.cpp index d495e63..984ccfb 100644 --- a/source/dbg/debug_menu_functions.cpp +++ b/source/dbg/debug_menu_functions.cpp @@ -8,21 +8,11 @@ #include "save_data_manager.h" #include "background_engine.h" #include "libstd_replacements.h" +#include "sound.h" -void dbg_menu_print_number(unsigned user_param) -{ - 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); -} - -void show_text_debug_screen(unsigned user_param) +void show_text_debug_screen(void *context, unsigned user_param) { + (void)context; (void)user_param; tte_set_ink(INK_DARK_GREY); @@ -31,8 +21,11 @@ void show_text_debug_screen(unsigned user_param) text_loop(SCRIPT_DEBUG); } -void show_debug_info_screen(unsigned user_param) +void show_debug_info_screen(void *context, unsigned user_param) { + (void)context; + (void)user_param; + char hexBuffer[16]; uint16_t charset[256]; load_localized_charset(charset, 3, ENGLISH); @@ -107,4 +100,20 @@ void show_debug_info_screen(unsigned user_param) } global_next_frame(); } +} + +void dbg_set_boolean_flag(void *context, unsigned user_param) +{ + bool *flag_ptr = (bool*)context; + *flag_ptr = (user_param != 0); +} + +void dbg_play_song(void *context, unsigned user_param) +{ + if(user_param == UINT32_MAX) + { + stop_song(); + return; + } + play_song(user_param, true); } \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index 4525723..fcf7db9 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -16,8 +16,6 @@ #include "button_menu.h" #include "dbg/debug_mode.h" #include "dbg/debug_menu.h" -// #include "soundbank.h" -// #include "soundbank_bin.h" #include "dex_handler.h" #include "pokedex.h" #include "global_frame_controller.h" @@ -222,7 +220,6 @@ int main_menu_loop() general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); - play_song(MOD_MAIN_MENU, true); while (true) { if (update) diff --git a/source/vertical_menu.cpp b/source/vertical_menu.cpp index 22f81f1..6d4c351 100644 --- a/source/vertical_menu.cpp +++ b/source/vertical_menu.cpp @@ -144,7 +144,6 @@ 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_) @@ -182,7 +181,6 @@ MenuInputHandleState vertical_menu::handle_input() if(focused_index_ >= current_viewport_end_index) { ++viewport_start_index_; - viewport_updated = true; } did_navigate = true; } @@ -192,7 +190,6 @@ MenuInputHandleState vertical_menu::handle_input() if(focused_index_ < viewport_start_index_) { --viewport_start_index_; - viewport_updated = true; } did_navigate = true; } @@ -201,10 +198,7 @@ MenuInputHandleState vertical_menu::handle_input() if(did_navigate) { const unsigned render_index = focused_index_ - viewport_start_index_; - if(viewport_updated) - { - update_viewport(); - } + update_viewport(); handle_selection_change(focused_index_, settings_.x, settings_.y + settings_.margin_top + (render_index * settings_.item_height)); return MenuInputHandleState::HANDLED; }