diff --git a/castlevania.yaml b/castlevania.yaml index 2bc4c59f..772bb522 100644 --- a/castlevania.yaml +++ b/castlevania.yaml @@ -520,7 +520,7 @@ segments: - [0x000BA6F0, asm, common/hud] - [0x000BC530, c, common/hud_params] # HUD_params is an struct associated to the HUD object - [0x000BC6D0, asm, common/renon_shop] - - [0x000BDFE0, asm] + - [0x000BDFE0, c, common/BDFE0] - [0x000BE4B0, c, common/menu_alloc_struct] # Contains functions for allocating menu-related structs - [0x000BE740, c, common/gameplay_common_textbox] - [0x000BEF40, asm, common/item] # Contains item / inventory handling code, as well as code for handling displaying these diff --git a/include/cv64.h b/include/cv64.h index d28382c5..c9d4da34 100644 --- a/include/cv64.h +++ b/include/cv64.h @@ -71,7 +71,8 @@ typedef enum MenuID { } MenuID; extern void end_master_display_list(void); -extern s32 menuButton_selectNextOption(s32* option, s16* param_2, s16 number_of_options); +s32 menuButton_selectNextOption(s32* option, s16* selection_delay_timer, s16 num_options); +u32 moveSelectionCursor(u32 button); extern void func_800010A0_1CA0(void); extern void func_8001248C_1308C(void); extern void func_8000C6D0(void); @@ -91,8 +92,9 @@ extern void player_status_init(void); #define ARRAY_START(arr) &arr[0] // Get start address of array #define ARRAY_END(arr) &arr[ARRAY_COUNT(arr)] // Get end address of array -#define SCREEN_WIDTH 320 -#define SCREEN_HEIGHT 240 +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 240 +#define NUM_FRAMEBUFFERS 3 // Text IDs for Forest of Silence #define FOREST_LOCKED_DOOR 1 @@ -183,4 +185,6 @@ extern void player_status_init(void); extern const u32 MENU_RED_BACKGROUND_DL; +extern u16 gFramebuffers[NUM_FRAMEBUFFERS][SCREEN_WIDTH * SCREEN_HEIGHT]; + #endif // CV64_H diff --git a/include/game/objects/menu/gameplay_menu_manager.h b/include/game/objects/menu/gameplay_menu_manager.h index 4b0fe76f..bdfcde3b 100644 --- a/include/game/objects/menu/gameplay_menu_manager.h +++ b/include/game/objects/menu/gameplay_menu_manager.h @@ -65,7 +65,6 @@ void GameplayMenuManager_outsideMenuLoop(GameplayMenuManager* self); void GameplayMenuManager_initMenu(GameplayMenuManager* self); void GameplayMenuManager_insideMenuLoop(GameplayMenuManager* self); void GameplayMenuManager_exitMenu(GameplayMenuManager* self); -u32 moveSelectionCursor(u32 button); MfdsState* GameplayCommonTextbox_getIfClosed(void); MfdsState* GameplayCommonTextbox_close(void); diff --git a/include/game/system_work.h b/include/game/system_work.h index 7af78392..795ca9bf 100644 --- a/include/game/system_work.h +++ b/include/game/system_work.h @@ -228,5 +228,7 @@ extern system_work sys; (GET_CONTROLLER(2).btns_pressed) | (GET_CONTROLLER(3).btns_pressed)), \ (buttons) \ ) +#define CONT_JOY_X(controller_id) (GET_CONTROLLER(controller_id).joy_x) +#define CONT_JOY_Y(controller_id) (GET_CONTROLLER(controller_id).joy_y) #endif diff --git a/linker/symbol_addrs.txt b/linker/symbol_addrs.txt index c873f7c8..558e5a74 100644 --- a/linker/symbol_addrs.txt +++ b/linker/symbol_addrs.txt @@ -1644,6 +1644,17 @@ D_8018BDF0 = 0x8018BDF0; // type:asciz segment:common size:0x0A // End of src/common/page_work.c =============================================== +// src/common/BDFE0.c ====================================================== + +// .text +copyFramebufferRect = 0x8013ADF0; // type:func segment:common +menuButton_selectNextOption = 0x8013B00C; // type:func segment:common +Model_moveWithController = 0x8013B108; // type:func segment:common +Model_copyPositionalParams = 0x8013B270; // type:func segment:common + +// End of src/common/BDFE0.c =============================================== + + // src/common/skybox_common_actors.c =========================================== // .text @@ -2333,7 +2344,6 @@ renonShop_calcItemList = 0x80139f1c; renonShop_calcBuyScreen = 0x8013a4f4; renonShop_displayTextWhenLeavingBuyScreen = 0x8013aa18; renonShop_destroy = 0x8013ab84; -menuButton_selectNextOption = 0x8013b00c; allocStruct = 0x8013b2c0; getNumberOfItemsInRenonShop = 0x8013c598; createScrollState = 0x8013cc20; diff --git a/src/common/BDFE0.c b/src/common/BDFE0.c new file mode 100644 index 00000000..1df4fc45 --- /dev/null +++ b/src/common/BDFE0.c @@ -0,0 +1,122 @@ +/** + * @file BDFE0.c + */ + +#include "cv64.h" +#include "gfx/model.h" +#include "system_work.h" + +// Reads a rectangular block of pixels from the active framebuffer into `dest` +void copyFramebufferRect(s32 arg0, s16 left, s16 top, s16 right, s16 bottom, u16* dest) { + s32 row; + s32 column; + + for (row = 0; row < SCREEN_HEIGHT; row++) { + if (row >= top && row <= bottom) { + for (column = 0; column < SCREEN_WIDTH; column += 4) { + if ((column >= left) && (column <= right)) { + *dest++ = gFramebuffers[sys.frameBuffer_index][row * SCREEN_WIDTH + column]; + } + if ((column >= (left - 1)) && (column < right)) { + *dest++ = gFramebuffers[sys.frameBuffer_index][row * SCREEN_WIDTH + column + 1]; + } + if ((column >= (left - 2)) && (column + 2 <= right)) { + *dest++ = gFramebuffers[sys.frameBuffer_index][row * SCREEN_WIDTH + column + 2]; + } + if ((column >= (left - 3)) && (column + 3 <= right)) { + *dest++ = gFramebuffers[sys.frameBuffer_index][row * SCREEN_WIDTH + column + 3]; + } + } + } + } +} + +/** + * Returns: + * 0: No movement happened + * 1: Moving one option forwards / down + * -1: Moving one option backwards / up + */ +s32 menuButton_selectNextOption(s32* option, s16* selection_delay_timer, s16 num_options) { + s32 ret = 0; + s32 roll_over; + + *selection_delay_timer = 0; + + if (num_options < 0) { + num_options *= -1; + roll_over = FALSE; + } else { + roll_over = TRUE; + } + + if (moveSelectionCursor(CONT_UP)) { + *option -= 1; + + if (*option < 0) { + ret = -1; + + if (roll_over) { + *option = num_options - 1; + } else { + *option = 0; + } + } + } + + if (ret) { + } + + if (moveSelectionCursor(CONT_DOWN)) { + *option += 1; + + if (*option >= num_options) { + ret = 1; + + if (roll_over) { + *option = 0; + } else { + *option = num_options - 1; + } + } + } + + return ret; +} + +void Model_moveWithController(u8 cont_number, Model* model) { + if (CONT_BTNS_HELD(cont_number, Z_TRIG)) { + if (CONT_BTNS_PRESSED(cont_number, CONT_UP) || CONT_JOY_Y(cont_number) > 25) { + model->position.z -= 1.0f; + } + if (CONT_BTNS_PRESSED(cont_number, CONT_DOWN) || CONT_JOY_Y(cont_number) < -25) { + model->position.z += 1.0f; + } + } else { + if (CONT_BTNS_PRESSED(cont_number, CONT_UP) || CONT_JOY_Y(cont_number) > 25) { + model->position.y += 1.0f; + } + if (CONT_BTNS_PRESSED(cont_number, CONT_DOWN) || CONT_JOY_Y(cont_number) < -25) { + model->position.y -= 1.0f; + } + } + + if (CONT_BTNS_PRESSED(cont_number, CONT_LEFT) || CONT_JOY_X(cont_number) < -25) { + model->position.x -= 1.0f; + } + if (CONT_BTNS_PRESSED(cont_number, CONT_RIGHT) || CONT_JOY_X(cont_number) > 25) { + model->position.x += 1.0f; + } +} + +void Model_copyPositionalParams(Model* src, Model* dest) { + dest->position.x = src->position.x; + dest->position.y = src->position.y; + dest->position.z = src->position.z; + dest->size.x = src->size.x; + dest->size.y = src->size.y; + dest->size.z = src->size.z; + dest->angle.pitch = src->angle.pitch; + dest->angle.yaw = src->angle.yaw; + dest->angle.roll = src->angle.roll; +} diff --git a/src/common/gameplay_menu_manager.c b/src/common/gameplay_menu_manager.c index 02068c58..0ead62f1 100644 --- a/src/common/gameplay_menu_manager.c +++ b/src/common/gameplay_menu_manager.c @@ -529,16 +529,16 @@ u32 moveSelectionCursor(u32 button) { /** * Check for the joystick directional inputs */ - if (GET_CONTROLLER(CONT_0).joy_y > 40) { + if (CONT_JOY_Y(CONT_0) > 40) { BITS_SET(selection_input, U_JPAD); } - if (GET_CONTROLLER(CONT_0).joy_y < -40) { + if (CONT_JOY_Y(CONT_0) < -40) { BITS_SET(selection_input, D_JPAD); } - if (GET_CONTROLLER(CONT_0).joy_x > 40) { + if (CONT_JOY_X(CONT_0) > 40) { BITS_SET(selection_input, R_JPAD); } - if (GET_CONTROLLER(CONT_0).joy_x < -40) { + if (CONT_JOY_X(CONT_0) < -40) { BITS_SET(selection_input, L_JPAD); } diff --git a/src/overlay/difficulty_and_character_select.c b/src/overlay/difficulty_and_character_select.c index 8d2fd4a8..ea53488a 100644 --- a/src/overlay/difficulty_and_character_select.c +++ b/src/overlay/difficulty_and_character_select.c @@ -394,12 +394,12 @@ void characterSelect_selectOption(characterSelect* self) { if (work->current_character_option == work->previous_character_option) { // Moving the lens to the left if ((work->current_character_option == work->previous_character_option) && - (CONT_BTNS_PRESSED(CONT_0, L_JPAD) || (sys.controllers[0].joy_x < -25))) { + (CONT_BTNS_PRESSED(CONT_0, L_JPAD) || (CONT_JOY_X(CONT_0) < -25))) { work->current_character_option--; } // Moving the lens to the right if ((work->current_character_option == work->previous_character_option) && - (CONT_BTNS_PRESSED(CONT_0, R_JPAD) || (sys.controllers[0].joy_x >= 26))) { + (CONT_BTNS_PRESSED(CONT_0, R_JPAD) || (CONT_JOY_X(CONT_0) >= 26))) { work->current_character_option++; } characterSelect_determineCharacterToSelect( @@ -409,7 +409,7 @@ void characterSelect_selectOption(characterSelect* self) { if (CONT_BTNS_PRESSED(CONT_0, A_BUTTON) || CONT_BTNS_PRESSED(CONT_0, (START_BUTTON | RECENTER_BUTTON))) { // Apply alternate costume if moving up + if the appropiate Special jewels were obtained - if (CONT_BTNS_PRESSED(CONT_0, U_JPAD) || (sys.controllers[0].joy_y >= 26)) { + if (CONT_BTNS_PRESSED(CONT_0, U_JPAD) || (CONT_JOY_Y(CONT_0) >= 26)) { // Make sure the player has finished the game before trying to assign the alternate costume if (((BITS_HAS( sys.SaveStruct_gameplay.flags, SAVE_FLAG_REINDHART_GOOD_ENDING diff --git a/src/overlay/textbox/library_puzzle.c b/src/overlay/textbox/library_puzzle.c index 1db88165..112381bd 100644 --- a/src/overlay/textbox/library_puzzle.c +++ b/src/overlay/textbox/library_puzzle.c @@ -462,7 +462,7 @@ s32 select_next_option( * `*selected_options_IDs & (1 << (*highlighted_option))` makes sure * to skip selecting the already-selected options */ - if ((CONT_BTNS_PRESSED(CONT_0, L_JPAD)) || (sys.controllers[0].joy_x < -25)) { + if ((CONT_BTNS_PRESSED(CONT_0, L_JPAD)) || (CONT_JOY_X(CONT_0) < -25)) { if (*selection_delay_timer == 0) { *selection_delay_timer = LIBRARY_PUZZLE_SELECTION_DELAY; do { @@ -474,7 +474,7 @@ s32 select_next_option( } else { (*selection_delay_timer)--; } - } else if ((CONT_BTNS_PRESSED(CONT_0, R_JPAD)) || (sys.controllers[0].joy_x >= 26)) { + } else if ((CONT_BTNS_PRESSED(CONT_0, R_JPAD)) || (CONT_JOY_X(CONT_0) >= 26)) { if (*selection_delay_timer == 0) { *selection_delay_timer = LIBRARY_PUZZLE_SELECTION_DELAY; do {