diff --git a/patches/linker/link_ntsc10.ld b/patches/linker/link_ntsc10.ld index d054458..8eed495 100644 --- a/patches/linker/link_ntsc10.ld +++ b/patches/linker/link_ntsc10.ld @@ -104,3 +104,11 @@ ntsc10_EXIDeselect = 0x81335838; ntsc10_EXISync = 0x81335134; ntsc10_EXIImm = 0x81334d4c; ntsc10_EXIImmEx = 0x81334fa8; + +ntsc10_all_element_alphas = 0x81465a9c; +ntsc10_update_element_alpha = 0x8130aa58; + +ntsc10_update_button_alphas = 0x81311a98; + +ntsc10_current_pal_buttons_language = 0; +ntsc10_pal_button_language_elements = 0; diff --git a/patches/linker/link_ntsc11.ld b/patches/linker/link_ntsc11.ld index f4c171b..a6c7b9c 100644 --- a/patches/linker/link_ntsc11.ld +++ b/patches/linker/link_ntsc11.ld @@ -104,3 +104,11 @@ ntsc11_EXIDeselect = 0x8135b298; ntsc11_EXISync = 0x8135ab5c; ntsc11_EXIImm = 0x8135a774; ntsc11_EXIImmEx = 0x8135a9d0; + +ntsc11_all_element_alphas = 0x8148a21c; +ntsc11_update_element_alpha = 0x8130a964; + +ntsc11_update_button_alphas = 0x81311ce8; + +ntsc11_current_pal_buttons_language = 0; +ntsc11_pal_button_language_elements = 0; diff --git a/patches/linker/link_ntsc12_001.ld b/patches/linker/link_ntsc12_001.ld index 0114570..0a32f83 100644 --- a/patches/linker/link_ntsc12_001.ld +++ b/patches/linker/link_ntsc12_001.ld @@ -99,3 +99,11 @@ ntsc12_001_EXIDeselect = 0x81364790; ntsc12_001_EXISync = 0x81363f4c; ntsc12_001_EXIImm = 0x81363b64; ntsc12_001_EXIImmEx = 0x81363dc0; + +ntsc12_001_all_element_alphas = 0x8148b7fc; +ntsc12_001_update_element_alpha = 0x8130acd8; + +ntsc12_001_update_button_alphas = 0x81312080; + +ntsc12_001_current_pal_buttons_language = 0; +ntsc12_001_pal_button_language_elements = 0; diff --git a/patches/linker/link_ntsc12_101.ld b/patches/linker/link_ntsc12_101.ld index 2161f9d..ca559c9 100644 --- a/patches/linker/link_ntsc12_101.ld +++ b/patches/linker/link_ntsc12_101.ld @@ -99,3 +99,11 @@ ntsc12_101_EXIDeselect = 0x813648f4; ntsc12_101_EXISync = 0x813640b0; ntsc12_101_EXIImm = 0x81363cc8; ntsc12_101_EXIImmEx = 0x81363f24; + +ntsc12_101_all_element_alphas = 0x8148bc9c; +ntsc12_101_update_element_alpha = 0x8130acf0; + +ntsc12_101_update_button_alphas = 0x81312098; + +ntsc12_101_current_pal_buttons_language = 0; +ntsc12_101_pal_button_language_elements = 0; diff --git a/patches/linker/link_pal10.ld b/patches/linker/link_pal10.ld index 76ec3d7..b262c47 100644 --- a/patches/linker/link_pal10.ld +++ b/patches/linker/link_pal10.ld @@ -101,3 +101,11 @@ pal10_EXIDeselect = 0x8135e878; pal10_EXISync = 0x8135e13c; pal10_EXIImm = 0x8135dd54; pal10_EXIImmEx = 0x8135dfb0; + +pal10_all_element_alphas = 0x814b611c; +pal10_update_element_alpha = 0x8130a87c; + +pal10_update_button_alphas = 0x81312580; + +pal10_current_pal_buttons_language = 0x814ad438; +pal10_pal_button_language_elements = 0x814b62fc; diff --git a/patches/linker/link_pal11.ld b/patches/linker/link_pal11.ld index 5a070fb..aad7608 100644 --- a/patches/linker/link_pal11.ld +++ b/patches/linker/link_pal11.ld @@ -99,3 +99,11 @@ pal11_EXIDeselect = 0x8135b1b8; pal11_EXISync = 0x8135aa7c; pal11_EXIImm = 0x8135a694; pal11_EXIImmEx = 0x8135a8f0; + +pal11_all_element_alphas = 0x81484edc; +pal11_update_element_alpha = 0x8130a964; + +pal11_update_button_alphas = 0x81311c14; + +pal11_current_pal_buttons_language = 0; +pal11_pal_button_language_elements = 0; diff --git a/patches/linker/link_pal12.ld b/patches/linker/link_pal12.ld index 9e4985d..05debca 100644 --- a/patches/linker/link_pal12.ld +++ b/patches/linker/link_pal12.ld @@ -100,3 +100,11 @@ pal12_EXIDeselect = 0x81367c6c; pal12_EXISync = 0x81367428; pal12_EXIImm = 0x81367040; pal12_EXIImmEx = 0x8136729c; + +pal12_all_element_alphas = 0x814b78dc; +pal12_update_element_alpha = 0x8130a9bc; + +pal12_update_button_alphas = 0x813126c0; + +pal12_current_pal_buttons_language = 0x814af730; +pal12_pal_button_language_elements = 0x814b7abc; diff --git a/patches/source/button_descriptions.c b/patches/source/button_descriptions.c new file mode 100644 index 0000000..4a12a51 --- /dev/null +++ b/patches/source/button_descriptions.c @@ -0,0 +1,79 @@ +#include "button_descriptions.h" + +#include "menu.h" +#include "attr.h" +#include "reloc.h" + +#define NUM_PAL_LANGUAGES 6 + +__attribute_reloc__ void (*update_button_alphas)(); + +__attribute_reloc__ all_element_alphas_t* all_element_alphas; + +__attribute_reloc__ u16 *current_pal_buttons_language; +__attribute_reloc__ element_alpha_state_t *pal_button_language_elements; + +static void update_gameplay_button_text() { + // Disable button descriptions used by the outer menu + update_element_alpha(&all_element_alphas->text.one_column.menu_selection, element_alpha_hidden); + update_element_alpha(&all_element_alphas->text.two_columns.left_cancel, element_alpha_hidden); + update_element_alpha(&all_element_alphas->text.two_columns.right_confirm, element_alpha_hidden); + + // And also disable button descriptions used by other menus + update_element_alpha(&all_element_alphas->text.three_columns.left_change, element_alpha_hidden); + update_element_alpha(&all_element_alphas->text.three_columns.centre_finish, element_alpha_hidden); + + // Show 'B: Cancel' on both the loader and start screens + update_element_alpha(&all_element_alphas->text.three_columns.centre_cancel, element_alpha_visible); + + // Show 'Control Stick: Select' and 'A: Confirm' just on the loader menu + update_element_alpha(&all_element_alphas->text.three_columns.left_select, current_gameselect_state == SUBMENU_GAMESELECT_LOADER ? element_alpha_visible : element_alpha_hidden); + update_element_alpha(&all_element_alphas->text.three_columns.right_confirm, current_gameselect_state == SUBMENU_GAMESELECT_LOADER ? element_alpha_visible : element_alpha_hidden); +} + +static void update_gameplay_button_icons() { + // Disable button icons used by the outer menu + update_element_alpha(&all_element_alphas->icons.one_column.control_stick, element_alpha_hidden); + update_element_alpha(&all_element_alphas->icons.two_columns.left_b_button, element_alpha_hidden); + update_element_alpha(&all_element_alphas->icons.two_columns.right_a_button, element_alpha_hidden); + + // Show 'B: Cancel' on both the loader and start screens + update_element_alpha(&all_element_alphas->icons.three_columns.centre_b_button, element_alpha_visible); + + // Show 'Control Stick: Select' and 'A: Confirm' just on the loader menu + update_element_alpha(&all_element_alphas->icons.three_columns.left_control_stick, current_gameselect_state == SUBMENU_GAMESELECT_LOADER ? element_alpha_visible : element_alpha_hidden); + update_element_alpha(&all_element_alphas->icons.three_columns.right_a_button, current_gameselect_state == SUBMENU_GAMESELECT_LOADER ? element_alpha_visible : element_alpha_hidden); +} + +static void update_pal_button_languages() { + if (!current_pal_buttons_language || !pal_button_language_elements) { + // Only PAL 1.0 and 1.2 have runtime-configurable languages; other versions don't need this additional step + return; + } + + for (int i = 0; i < NUM_PAL_LANGUAGES; i++) { + element_alpha_update_state_t language_state = (i == *current_pal_buttons_language) ? element_alpha_visible : element_alpha_hidden; + update_element_alpha(&pal_button_language_elements[i], language_state); + } +} + +__attribute_used__ void patch_update_button_alphas() { + bool ran_default_code = false; + + switch (*cur_menu_id) { + case MENU_GAMESELECT_TRANSITION_ID: + update_gameplay_button_text(); + update_gameplay_button_icons(); + break; + + default: + update_button_alphas(); + ran_default_code = true; + break; + } + + if (!ran_default_code) { + // If we didn't run the default code, we also have to take care of updating the per-language elements on PAL systems + update_pal_button_languages(); + } +} diff --git a/patches/source/button_descriptions.h b/patches/source/button_descriptions.h new file mode 100644 index 0000000..a3ac435 --- /dev/null +++ b/patches/source/button_descriptions.h @@ -0,0 +1,43 @@ +#include + +#include "element_alpha.h" + +typedef struct { + struct { + struct { + element_alpha_state_t left_control_stick; + element_alpha_state_t centre_b_button; + element_alpha_state_t right_a_button; + } three_columns; + + struct { + element_alpha_state_t control_stick; + } one_column; + + struct { + element_alpha_state_t left_b_button; + element_alpha_state_t right_a_button; + } two_columns; + } icons; + + struct { + struct { + element_alpha_state_t menu_selection; + } one_column; + + struct { + element_alpha_state_t left_cancel; + element_alpha_state_t right_confirm; + } two_columns; + + struct { + element_alpha_state_t left_select; + element_alpha_state_t left_change; + element_alpha_state_t centre_cancel; + element_alpha_state_t centre_finish; + element_alpha_state_t right_confirm; + } three_columns; + } text; + + // There are more elements past this point that relate to other elements, e.g. menus +} all_element_alphas_t; diff --git a/patches/source/element_alpha.c b/patches/source/element_alpha.c new file mode 100644 index 0000000..d0e47ac --- /dev/null +++ b/patches/source/element_alpha.c @@ -0,0 +1,5 @@ +#include "element_alpha.h" + +#include "attr.h" + +__attribute_reloc__ void (*update_element_alpha)(element_alpha_state_t *element, element_alpha_update_state_t new_state); diff --git a/patches/source/element_alpha.h b/patches/source/element_alpha.h new file mode 100644 index 0000000..fef4ca0 --- /dev/null +++ b/patches/source/element_alpha.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +typedef struct { + u16 current_alpha; // Ranges from 0 to (fade_duration + start_delay) + u16 fade_duration; // Frames; typically 0x14 + u16 start_delay; // Frames; typically 0 + u16 frame_counter; // Incremented with every update + u8 unk0; + u8 max_output; + u16 unknown_output_multiplier; + u32 unk1; +} element_alpha_state_t; + +typedef enum { + element_alpha_visible, + element_alpha_hidden, + element_alpha_dimmed +} element_alpha_update_state_t; + +extern void (*update_element_alpha)(element_alpha_state_t *element, element_alpha_update_state_t new_state); diff --git a/patches/source/menu.h b/patches/source/menu.h index ffd7a9f..b710ea7 100644 --- a/patches/source/menu.h +++ b/patches/source/menu.h @@ -1,3 +1,5 @@ +#include + #define MENU_SELECTION_ID 0 #define MENU_GAMESELECT_ID 1 #define MENU_GAMESELECT_TRANSITION_ID 2 @@ -25,6 +27,8 @@ #define SOUND_CARD_MOVE 0x0b #define SOUND_CARD_ERROR 0x0d +extern u32 current_gameselect_state; + extern int selected_slot; extern int top_line_num; diff --git a/patches/source/patch.s b/patches/source/patch.s index 22d128f..3970361 100644 --- a/patches/source/patch.s +++ b/patches/source/patch.s @@ -115,3 +115,6 @@ patch_inst_pal "_patch_menu_alpha_setup" 0x81312c3c 0x81312284 0x81312d7c bl pre patch_inst_pal "_fix_video_mode_init" 0x81300520 0x81300520 0x81300610 bl get_tvmode patch_inst_global "_patch_pre_main" 0x81300090 bl pre_main + +patch_inst_ntsc "_patch_update_button_alphas" 0x81312104 0x81312354 0x813126ec 0x81312704 bl patch_update_button_alphas +patch_inst_pal "_patch_update_button_alphas" 0x81312c38 0x81312280 0x81312d78 bl patch_update_button_alphas