// Block properties, some cutscene graphics #include "sm_rtl.h" #include "ida_types.h" #include "variables.h" #include "funcs.h" static const uint8 kAlignPos_Tab1[512] = { 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 9, 10, 11, 12, 13, 14, 15, 16, 16, 14, 12, 10, 8, 6, 4, 2, 2, 4, 6, 8, 10, 12, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 8, 8, 8, 8, 4, 4, 4, 4, 0, 0, 0, 0, 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 20, 20, 20, 20, 20, 20, 20, 20, 16, 14, 12, 10, 8, 6, 4, 2, 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 15, 12, 9, 6, 3, 20, 20, 20, 20, 20, 20, 14, 11, 8, 5, 2, 0, 0, 0, 0, 0, 16, 13, 10, 7, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static const uint8 kAlignYPos_Tab0[512] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 9, 10, 11, 12, 13, 14, 15, 16, 16, 14, 12, 10, 8, 6, 4, 2, 2, 4, 6, 8, 10, 12, 14, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 8, 8, 8, 8, 4, 4, 4, 4, 0, 0, 0, 0, 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 20, 20, 20, 20, 20, 20, 20, 20, 16, 14, 12, 10, 8, 6, 4, 2, 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 15, 12, 9, 6, 3, 20, 20, 20, 20, 20, 20, 14, 11, 8, 5, 2, 0, 0, 0, 0, 0, 16, 13, 10, 7, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; ////////////////////////////////////////////////////////////// // BANK 94 ////////////////////////////////////////////////////////////// static const uint8 kTab948E54[20] = { 0, 0, 0x80, 0x80, 0, 0x80, 0, 0x80, 0, 0, 0, 0x80, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, }; static const uint16 kBlockColl_Horiz_Slope_NonSquare_Tab[64] = { 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0, 0x100, 0x1000, 0xb0, 0x1000, 0xb0, 0, 0x100, 0, 0x100, 0x1000, 0xc0, 0, 0x100, 0x1000, 0xc0, 0x1000, 0xc0, 0x800, 0xd8, 0x800, 0xd8, 0x600, 0xf0, 0x600, 0xf0, 0x600, 0xf0, 0x4000, 0x80, 0x4000, 0x80, 0x6000, 0x50, 0x6000, 0x50, 0x6000, 0x50, }; #define fnkPlmHeaderDefPtrs 0x949139 #define off_9492D9 ((uint16*)RomPtr(0x9492d9)) #define off_9492E9 ((uint16*)RomPtr(0x9492e9)) #define kPlmHeaderDefPtrs ((uint16*)RomPtr(0x949139)) uint16 PostGrappleColl_Horiz_Slope_NonSquare(uint16 k) { // 0x948000 int16 v1; char v3; int16 v5; char v6; int16 v8; if (!(samus_collision_direction & 1)) { uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); v1 = samus_x_pos >> 4; if (v1 != mod) return -1; temp_collision_DD4 = R32 & 0xF; temp_collision_DD6 = 16 * (BTS[k] & 0x1F); if ((BTS[k] & 0x40) != 0) { if (BTS[k] & 0x80) v3 = samus_y_pos ^ 0xF; else v3 = samus_y_pos; uint16 v4 = temp_collision_DD6 + (v3 & 0xF); uint16 result = (kAlignPos_Tab1[v4] & 0x1F) - temp_collision_DD4 - 1; if ((kAlignPos_Tab1[v4] & 0x1F) - temp_collision_DD4 != 1 && (result & 0x8000u) != 0) return -1; return result; } return PostGrappleColl_Horiz_Solid(); } uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); v5 = samus_x_pos >> 4; if (v5 != mod) return -1; temp_collision_DD4 = R32 & 0xF; temp_collision_DD6 = 16 * (BTS[k] & 0x1F); if (BTS[k] & 0x40) return PostGrappleColl_Horiz_Solid(); if (BTS[k] & 0x80) v6 = samus_y_pos ^ 0xF; else v6 = samus_y_pos; uint16 v7 = temp_collision_DD6 + (v6 & 0xF); v8 = (kAlignPos_Tab1[v7] & 0x1F) - temp_collision_DD4 - 1; if ((kAlignPos_Tab1[v7] & 0x1F) - temp_collision_DD4 == 1 || v8 < 0) return ~v8; else return -1; } uint16 PostGrappleColl_Vert_Slope_NonSquare(uint16 k) { // 0x9480E0 int16 v1; int16 v3; char v4; int16 v6; int16 v7; char v8; int16 v10; if (!(samus_collision_direction & 1)) { uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); v1 = samus_x_pos >> 4; if (v1 != mod) return -1; temp_collision_DD4 = R32 & 0xF; temp_collision_DD6 = 16 * (BTS[k] & 0x1F); v3 = BTS[k]; if (v3 & 0x80) { if ((v3 & 0x40) != 0) v4 = samus_x_pos ^ 0xF; else v4 = samus_x_pos; uint16 v5 = temp_collision_DD6 + (v4 & 0xF); uint16 result = (kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 - 1; if ((kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 != 1 && (result & 0x8000u) != 0) return -1; return result; } return PostGrappleColl_Vert_Solid(); } uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); v6 = samus_x_pos >> 4; if (v6 != mod) return -1; temp_collision_DD4 = R32 & 0xF; temp_collision_DD6 = 16 * (BTS[k] & 0x1F); v7 = BTS[k]; if (v7 & 0x80) return PostGrappleColl_Vert_Solid(); if ((v7 & 0x40) != 0) v8 = samus_x_pos ^ 0xF; else v8 = samus_x_pos; uint16 v9 = temp_collision_DD6 + (v8 & 0xF); v10 = (kAlignYPos_Tab0[v9] & 0x1F) - temp_collision_DD4 - 1; if ((kAlignYPos_Tab0[v9] & 0x1F) - temp_collision_DD4 == 1 || v10 < 0) return ~v10; else return -1; } uint16 PostGrappleColl_Horiz_Slope_Square(uint16 k) { // 0x9481B8 temp_collision_DD4 = 4 * (BTS[k] & 0x1F); temp_collision_DD6 = BTS[k] >> 6; uint16 v1 = temp_collision_DD4 + (temp_collision_DD6 ^ ((uint8)(R32 & 8) >> 3)); if (!R26_) { if ((((uint8)samus_y_radius + (uint8)samus_y_pos - 1) & 8) == 0) { if (!kTab948E54[v1]) return -1; goto LABEL_10; } goto LABEL_7; } if (R26_ != R28_ || (((uint8)samus_y_pos - (uint8)samus_y_radius) & 8) == 0) { LABEL_7: if (kTab948E54[v1]) goto LABEL_10; } if (!kTab948E54[v1 ^ 2]) return -1; LABEL_10: if (samus_collision_direction & 1) return R32 & 7; else return R32 & 7 ^ 7; } uint16 PostGrappleColl_Vertical_Slope_Square(uint16 k) { // 0x948230 temp_collision_DD4 = 4 * (BTS[k] & 0x1F); temp_collision_DD6 = BTS[k] >> 6; uint16 v1 = temp_collision_DD4 + (temp_collision_DD6 ^ ((uint8)(R32 & 8) >> 2)); if (!R26_) { if ((((uint8)samus_x_radius + (uint8)samus_x_pos - 1) & 8) == 0) { if (!kTab948E54[v1]) return -1; goto LABEL_10; } goto LABEL_7; } if (R26_ != R28_ || (((uint8)samus_x_pos - (uint8)samus_x_radius) & 8) == 0) { LABEL_7: if (kTab948E54[v1]) goto LABEL_10; } if (!kTab948E54[v1 ^ 1]) return -1; LABEL_10: if (samus_collision_direction & 1) return R32 & 7; else return R32 & 7 ^ 7; } uint16 ClearCarry_0(void) { // 0x9482A7 return -1; } uint16 PostGrappleColl_Horiz_Slope(void) { // 0x9482A9 if ((BTS[cur_block_index] & 0x1Fu) < 5) return PostGrappleColl_Horiz_Slope_Square(cur_block_index); else return PostGrappleColl_Horiz_Slope_NonSquare(cur_block_index); } uint16 PostGrappleColl_Horiz_Solid(void) { // 0x9482BE return R32 & 0xF; } uint16 PostGrappleColl_Vert_Slope(void) { // 0x9482C5 if ((BTS[cur_block_index] & 0x1Fu) < 5) return PostGrappleColl_Vertical_Slope_Square(cur_block_index); else return PostGrappleColl_Vert_Slope_NonSquare(cur_block_index); } uint16 PostGrappleColl_Vert_Solid(void) { // 0x9482DA return R32 & 0xF; } static Func_U16 *const kPostGrappleColl_Horiz[16] = { // 0x948321 ClearCarry_0, PostGrappleColl_Horiz_Slope, ClearCarry_0, ClearCarry_0, ClearCarry_0, ClearCarry_0, ClearCarry_0, ClearCarry_0, PostGrappleColl_Horiz_Solid, PostGrappleColl_Horiz_Solid, PostGrappleColl_Horiz_Solid, PostGrappleColl_Horiz_Solid, PostGrappleColl_Horiz_Solid, PostGrappleColl_Horiz_Solid, PostGrappleColl_Horiz_Solid, PostGrappleColl_Horiz_Solid, }; static Func_U16 *const kPostGrappleColl_Vert[16] = { ClearCarry_0, PostGrappleColl_Vert_Slope, ClearCarry_0, ClearCarry_0, ClearCarry_0, ClearCarry_0, ClearCarry_0, ClearCarry_0, PostGrappleColl_Vert_Solid, PostGrappleColl_Vert_Solid, PostGrappleColl_Vert_Solid, PostGrappleColl_Vert_Solid, PostGrappleColl_Vert_Solid, PostGrappleColl_Vert_Solid, PostGrappleColl_Vert_Solid, PostGrappleColl_Vert_Solid, }; uint16 PostGrappleColl_Horiz(uint16 k) { cur_block_index = k >> 1; return kPostGrappleColl_Horiz[(uint16)((uint8)((uint16)(level_data[k >> 1] & 0xF000) >> 8) >> 3) >> 1](); } uint16 PostGrappleColl_Vert(uint16 k) { // 0x948338 cur_block_index = k >> 1; return kPostGrappleColl_Vert[(uint16)((uint8)((uint16)(level_data[k >> 1] & 0xF000) >> 8) >> 3) >> 1](); } void PostGrappleCollisionDetect_Right(void) { // 0x94834F int16 v0; int16 v2; samus_collision_direction = 1; distance_to_eject_samus_left = 0; Samus_GetYposSpan(); uint16 prod = Mult8x8((uint16)(samus_y_pos - samus_y_radius) >> 4, room_width_in_blocks); R22_ = samus_x_subpos; R24_ = samus_x_pos; R32 = samus_x_radius + samus_x_pos - 1; v0 = R32 >> 4; cur_block_index = prod + v0; uint16 v1 = 2 * cur_block_index; do { v2 = PostGrappleColl_Horiz(v1); if (v2 >= 0) { uint16 v3 = v2 + 1; if (v3 >= distance_to_eject_samus_left) distance_to_eject_samus_left = v3; } v1 += room_width_in_blocks + room_width_in_blocks; --R26_; } while ((R26_ & 0x8000u) == 0); } void PostGrappleCollisionDetect_Left(void) { // 0x9483B1 int16 v0; int16 v2; samus_collision_direction = 0; distance_to_eject_samus_right = 0; Samus_GetYposSpan(); uint16 prod = Mult8x8((uint16)(samus_y_pos - samus_y_radius) >> 4, room_width_in_blocks); R22_ = samus_x_subpos; R24_ = samus_x_pos; R32 = samus_x_pos - samus_x_radius; v0 = (uint16)(samus_x_pos - samus_x_radius) >> 4; cur_block_index = prod + v0; uint16 v1 = 2 * cur_block_index; do { v2 = PostGrappleColl_Horiz(v1); if (v2 >= 0) { uint16 v3 = v2 + 1; if (v3 >= distance_to_eject_samus_right) distance_to_eject_samus_right = v3; } v1 += room_width_in_blocks + room_width_in_blocks; --R26_; } while ((R26_ & 0x8000u) == 0); } void PostGrappleCollisionDetect_Down(void) { // 0x94840F int16 v0; int16 v2; samus_collision_direction = 3; distance_to_eject_samus_up = 0; Samus_GetXposSpan(); R22_ = samus_y_subpos; R24_ = samus_y_pos; R32 = samus_y_radius + samus_y_pos - 1; uint16 prod = Mult8x8(R32 >> 4, room_width_in_blocks); v0 = (uint16)(samus_x_pos - samus_x_radius) >> 4; cur_block_index = prod + v0; uint16 v1 = 2 * cur_block_index; do { v2 = PostGrappleColl_Vert(v1); if (v2 >= 0) { uint16 v3 = v2 + 1; if (v3 >= distance_to_eject_samus_up) distance_to_eject_samus_up = v3; } v1 += 2; --R26_; } while ((R26_ & 0x8000u) == 0); } void PostGrappleCollisionDetect_Up(void) { // 0x94846A int16 v0; int16 v2; samus_collision_direction = 2; distance_to_eject_samus_down = 0; Samus_GetXposSpan(); R22_ = samus_y_subpos; R24_ = samus_y_pos; R32 = samus_y_pos - samus_y_radius; uint16 prod = Mult8x8((uint16)(samus_y_pos - samus_y_radius) >> 4, room_width_in_blocks); v0 = (uint16)(samus_x_pos - samus_x_radius) >> 4; cur_block_index = prod + v0; uint16 v1 = 2 * cur_block_index; do { v2 = PostGrappleColl_Vert(v1); if (v2 >= 0) { uint16 v3 = v2 + 1; if (v3 >= distance_to_eject_samus_down) distance_to_eject_samus_down = v3; } v1 += 2; --R26_; } while ((R26_ & 0x8000u) == 0); } void PostGrappleCollisionDetect_X(void) { // 0x9484C4 PostGrappleCollisionDetect_Right(); PostGrappleCollisionDetect_Left(); } void PostGrappleCollisionDetect_Y(void) { // 0x9484CD PostGrappleCollisionDetect_Down(); PostGrappleCollisionDetect_Up(); } uint8 BlockColl_Horiz_Slope_NonSquare(void) { // 0x9484D6 uint16 v2; if ((current_slope_bts & 0x80) != 0 || __PAIR32__(samus_y_speed, samus_y_subspeed)) return 0; uint16 v1 = 4 * (current_slope_bts & 0x1F); HIBYTE(v2) = R18_; LOBYTE(v2) = HIBYTE(R20_); if ((R18_ & 0x8000u) == 0) { Multiply16x16(v2, kBlockColl_Horiz_Slope_NonSquare_Tab[(v1 >> 1) + 1]); R20_ = mult_product_lo; R18_ = mult_product_hi; } else { Multiply16x16(-v2, kBlockColl_Horiz_Slope_NonSquare_Tab[(v1 >> 1) + 1]); Negate32(&mult_product_hi, &mult_product_lo, &R18_, &R20_); } return 0; } uint8 BlockColl_Vert_Slope_NonSquare(uint16 k) { // 0x9486FE int16 v1; int16 v3; char v4; uint16 v5; int16 v6; int16 v7; int16 v8; int16 v9; char v10; uint16 v11; int16 v12; int16 v13; if (samus_collision_direction & 1) { uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); v8 = samus_x_pos >> 4; if (v8 == mod) { temp_collision_DD4 = ((uint8)samus_y_radius + (uint8)R24_ - 1) & 0xF; temp_collision_DD6 = 16 * (BTS[k] & 0x1F); v9 = BTS[k]; if (!(v9 & 0x80) && ((v9 & 0x40) != 0 ? (v10 = samus_x_pos ^ 0xF) : (v10 = samus_x_pos), (v11 = temp_collision_DD6 + (v10 & 0xF), v12 = (kAlignYPos_Tab0[v11] & 0x1F) - temp_collision_DD4 - 1, (kAlignYPos_Tab0[v11] & 0x1F) - temp_collision_DD4 == 1) || v12 < 0)) { v13 = R18_ + v12; if (v13 < 0) v13 = 0; R18_ = v13; R20_ = 0; return 1; } else { return 0; } } else { return 0; } } else { uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); v1 = samus_x_pos >> 4; if (v1 == mod) { temp_collision_DD4 = ((uint8)R24_ - (uint8)samus_y_radius) & 0xF ^ 0xF; temp_collision_DD6 = 16 * (BTS[k] & 0x1F); v3 = BTS[k]; if ((v3 & 0x80) && ((v3 & 0x40) != 0 ? (v4 = samus_x_pos ^ 0xF) : (v4 = samus_x_pos), (v5 = temp_collision_DD6 + (v4 & 0xF), v6 = (kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 - 1, (kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 == 1) || v6 < 0)) { v7 = R18_ + v6; if (v7 < 0) v7 = 0; R18_ = v7; R20_ = 0; return 1; } else { return 0; } } else { return 0; } } } void Samus_AlignYPosSlope(void) { // 0x9487F4 int16 v0; char v1; int16 v2; int16 v3; char v4; int16 v6; if ((enable_horiz_slope_coll & 2) != 0) { R26_ = samus_x_pos; R28_ = samus_y_radius + samus_y_pos - 1; g_word_7E001E = 0; R32 = 0; CalculateBlockAt(); if ((level_data[cur_block_index] & 0xF000) == 4096 && (BTS[cur_block_index] & 0x1Fu) >= 5) { temp_collision_DD4 = ((uint8)samus_y_radius + (uint8)samus_y_pos - 1) & 0xF; temp_collision_DD6 = 16 * (BTS[cur_block_index] & 0x1F); v0 = BTS[cur_block_index]; if (!(v0 & 0x80)) { v1 = (v0 & 0x40) != 0 ? samus_x_pos ^ 0xF : samus_x_pos; v2 = (kAlignYPos_Tab0[(uint16)(temp_collision_DD6 + (v1 & 0xF))] & 0x1F) - temp_collision_DD4 - 1; if (v2 < 0) { samus_y_pos += v2; samus_pos_adjusted_by_slope_flag = 1; } } } R26_ = samus_x_pos; R28_ = samus_y_pos - samus_y_radius; g_word_7E001E = 0; R32 = 0; CalculateBlockAt(); if ((level_data[cur_block_index] & 0xF000) == 4096 && (BTS[cur_block_index] & 0x1Fu) >= 5) { temp_collision_DD4 = ((uint8)samus_y_pos - (uint8)samus_y_radius) & 0xF ^ 0xF; temp_collision_DD6 = 16 * (BTS[cur_block_index] & 0x1F); v3 = BTS[cur_block_index]; if (v3 & 0x80) { if ((v3 & 0x40) != 0) v4 = samus_x_pos ^ 0xF; else v4 = samus_x_pos; uint16 v5 = temp_collision_DD6 + (v4 & 0xF); v6 = (kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 - 1; if ((kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 == 1 || v6 < 0) { samus_y_pos -= v6; samus_pos_adjusted_by_slope_flag = 1; } } } } } uint8 BlockColl_Horiz_Slope_Square(uint16 a, uint16 k) { // 0x948D2B int16 v4; int16 v5; temp_collision_DD4 = 4 * a; temp_collision_DD6 = BTS[k] >> 6; uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R32 & 8) >> 3)); if (!R26_) { if ((((uint8)samus_y_radius + (uint8)samus_y_pos - 1) & 8) == 0) { if (!kTab948E54[v2]) return 0; goto LABEL_10; } goto LABEL_7; } if (R26_ != R28_ || (((uint8)samus_y_pos - (uint8)samus_y_radius) & 8) == 0) { LABEL_7: if (kTab948E54[v2]) goto LABEL_10; } if (!kTab948E54[v2 ^ 2]) return 0; LABEL_10: R20_ = 0; if ((R18_ & 0x8000u) != 0) { v5 = samus_x_radius + (R32 | 7) + 1 - samus_x_pos; if (v5 >= 0) v5 = 0; R18_ = v5; samus_x_subpos = 0; return 1; } else { v4 = (__PAIR32__((R32 & 0xFFF8) - samus_x_radius, R32 & 0xFFF8) - __PAIR32__(samus_x_pos, samus_x_radius)) >> 16; if (v4 < 0) v4 = 0; R18_ = v4; samus_x_subpos = -1; return 1; } } uint8 BlockColl_Vert_Slope_Square(uint16 a, uint16 k) { // 0x948DBD int16 v4; int16 v5; temp_collision_DD4 = 4 * a; temp_collision_DD6 = BTS[k] >> 6; uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R32 & 8) >> 2)); if (!R26_) { if ((((uint8)samus_x_radius + (uint8)samus_x_pos - 1) & 8) == 0) { if (!kTab948E54[v2]) return 0; goto LABEL_10; } goto LABEL_7; } if (R26_ != R28_ || (((uint8)samus_x_pos - (uint8)samus_x_radius) & 8) == 0) { LABEL_7: if (kTab948E54[v2]) goto LABEL_10; } if (!kTab948E54[v2 ^ 1]) return 0; LABEL_10: R20_ = 0; if ((R18_ & 0x8000u) != 0) { v5 = samus_y_radius + (R32 | 7) + 1 - samus_y_pos; if (v5 >= 0) v5 = 0; R18_ = v5; samus_y_subpos = 0; return 1; } else { v4 = (__PAIR32__((R32 & 0xFFF8) - samus_y_radius, R32 & 0xFFF8) - __PAIR32__(samus_y_pos, samus_y_radius)) >> 16; if (v4 < 0) v4 = 0; R18_ = v4; samus_y_subpos = -1; samus_pos_adjusted_by_slope_flag = 1; return 1; } } uint8 ClearCarry_1(void) { // 0x948E7D return 0; } uint8 ClearCarry_2(void) { // 0x948E7F return 0; } uint8 ClearCarry_3(void) { // 0x948E81 return 0; } void BlockColl_SpikeBlock_BTS0(void) { // 0x948E83 if ((area_index != 3 || CheckBossBitForCurArea(1u) & 1) && !samus_invincibility_timer) { samus_invincibility_timer = 60; samus_knockback_timer = 10; samus_periodic_damage += 60; knockback_x_dir = ((*(uint16 *)&samus_pose_x_dir ^ 0xC) & 8) != 0; } } void BlockColl_SpikeBlock_BTS1(void) { // 0x948ECF if (!samus_invincibility_timer) { samus_invincibility_timer = 60; samus_knockback_timer = 10; samus_periodic_damage += 16; knockback_x_dir = ((*(uint16 *)&samus_pose_x_dir ^ 0xC) & 8) != 0; } } void BlockColl_SpikeBlock_BTS3(void) { // 0x948F0A if (!samus_invincibility_timer) { samus_invincibility_timer = 60; samus_knockback_timer = 10; samus_periodic_damage += 16; knockback_x_dir = ((*(uint16 *)&samus_pose_x_dir ^ 0xC) & 8) != 0; } } uint8 SetCarry(void) { return 1; } uint8 ClearCarry_4(void) { // 0x948F47 return 0; } uint8 BlockColl_Horiz_SolidShootGrappleBlock(void) { // 0x948F49 int16 v0; int16 v2; R20_ = 0; if ((R18_ & 0x8000u) != 0) { v2 = samus_x_radius + (R32 | 0xF) + 1 - samus_x_pos; if (v2 >= 0) v2 = 0; R18_ = v2; samus_x_subpos = 0; return 1; } else { v0 = (R32 & 0xFFF0) - samus_x_radius - samus_x_pos; if (v0 < 0) v0 = 0; R18_ = v0; samus_x_subpos = -1; return 1; } } uint8 BlockColl_Vert_SolidShootGrappleBlock(void) { // 0x948F82 int16 v0; int16 v2; R20_ = 0; if ((R18_ & 0x8000u) != 0) { v2 = samus_y_radius + (R32 | 0xF) + 1 - samus_y_pos; if (v2 >= 0) v2 = 0; R18_ = v2; samus_y_subpos = 0; return 1; } else { v0 = (R32 & 0xFFF0) - samus_y_radius - samus_y_pos; if (v0 < 0) v0 = 0; R18_ = v0; samus_y_subpos = -1; return 1; } } uint8 BlockColl_Horiz_Slope(void) { // 0x948FBB uint16 v0 = BTS[cur_block_index] & 0x1F; if (v0 < 5u) return BlockColl_Horiz_Slope_Square(v0, cur_block_index); current_slope_bts = BTS[cur_block_index]; return BlockColl_Horiz_Slope_NonSquare(); } uint8 BlockColl_Vert_Slope(void) { // 0x948FDA uint16 v0 = BTS[cur_block_index] & 0x1F; if (v0 < 5u) return BlockColl_Vert_Slope_Square(v0, cur_block_index); current_slope_bts = *(uint16 *)&BTS[cur_block_index]; return BlockColl_Vert_Slope_NonSquare(cur_block_index); } uint8 ClearCarry_5(void) { // 0x949018 return 0; } uint8 BlockColl_Vert_SpikeAir(void) { // 0x94901A return 0; } void SetCarry_Spikeblk(void) { } static Func_V *const kBlockColl_SpikeBlock[16] = { // 0x94904B BlockColl_SpikeBlock_BTS0, BlockColl_SpikeBlock_BTS1, SetCarry_Spikeblk, BlockColl_SpikeBlock_BTS3, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, SetCarry_Spikeblk, }; uint8 BlockColl_Horiz_SpikeBlock(void) { kBlockColl_SpikeBlock[(uint16)((2 * *(uint16 *)&BTS[cur_block_index]) & 0x1FF) >> 1](); return BlockColl_Horiz_SolidShootGrappleBlock(); } uint8 BlockColl_Vert_SpikeBlock(void) { // 0x94905D kBlockColl_SpikeBlock[(uint16)((2 * *(uint16 *)&BTS[cur_block_index]) & 0x1FF) >> 1](); return BlockColl_Vert_SolidShootGrappleBlock(); } uint8 BlockColl_Horiz_SpecialAir(void) { // 0x94906F int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) != 0) { R34 = off_9492D9[area_index]; uint8 *v2 = RomPtr_94(R34); return SpawnPLM(*(uint16 *)&v2[(uint16)(2 * (v0 & 0x7F))]) & 1; } else { SpawnPLM(kPlmHeaderDefPtrs[v0]); return 0; } } uint8 BlockColl_Vert_SpecialAir(void) { // 0x94909D int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) != 0) { R34 = off_9492D9[area_index]; uint8 *v2 = RomPtr_94(R34); return SpawnPLM(*(uint16 *)&v2[(uint16)(2 * (v0 & 0x7F))]) & 1; } else { SpawnPLM(kPlmHeaderDefPtrs[v0]); return 0; } } uint8 BlockColl_Horiz_SpecialBlock(void) { // 0x9490CB int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) != 0) { R34 = off_9492E9[area_index]; uint8 *v3 = RomPtr_94(R34); uint8 v4 = SpawnPLM(*(uint16 *)&v3[(uint16)(2 * (v0 & 0x7F))]) & 1; if (v4) return BlockColl_Horiz_SolidShootGrappleBlock(); return v4; } else { uint8 v1 = SpawnPLM(kPlmHeaderDefPtrs[v0]) & 1; if (v1 & 1) return BlockColl_Horiz_SolidShootGrappleBlock(); return v1; } } uint8 BlockColl_Vert_SpecialBlock(void) { // 0x949102 int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) != 0) { R34 = off_9492E9[area_index]; uint16 *v3 = (uint16*)RomPtr_94(R34); uint8 v4 = SpawnPLM(v3[v0 & 0x7F]) & 1; if (v4) return BlockColl_Vert_SolidShootGrappleBlock(); return v4; } else { uint8 v1 = SpawnPLM(kPlmHeaderDefPtrs[v0]) & 1; if (v1) return BlockColl_Vert_SolidShootGrappleBlock(); return v1; } } #define off_94936B ((uint16*)RomPtr(0x94936b)) uint8 BlockColl_Horiz_BombableAir(void) { // 0x9492F9 int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) == 0) SpawnPLM(off_94936B[v0]); return 0; } uint8 BlockColl_Vert_BombableAir(void) { // 0x949313 int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) == 0) SpawnPLM(off_94936B[v0]); return 0; } uint8 BlockColl_Horiz_BombBlock(void) { // 0x94932D int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) != 0) return BlockColl_Horiz_SolidShootGrappleBlock(); uint8 v1 = SpawnPLM(off_94936B[v0]) & 1; if (v1) return BlockColl_Horiz_SolidShootGrappleBlock(); else return v1; } uint8 BlockColl_Vert_BombBlock(void) { // 0x94934C int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) != 0) return BlockColl_Vert_SolidShootGrappleBlock(); uint8 v1 = SpawnPLM(off_94936B[v0]) & 1; if (v1) return BlockColl_Vert_SolidShootGrappleBlock(); else return v1; } uint8 BlockColl_Horiz_Door(void) { // 0x94938B door_transition_function = FUNC16(DoorTransitionFunction_HandleElevator); door_bts = BTS[cur_block_index]; uint16 v0 = *(uint16 *)RomPtr_8F(door_list_pointer + 2 * ((uint8)door_bts & 0x7Fu)); if ((get_DoorDef(v0)->room_definition_ptr & 0x8000u) == 0) { if (samus_pose < kGameState_9_HitDoorBlock) elevator_flags = 1; return BlockColl_Horiz_SolidShootGrappleBlock(); } else { door_def_ptr = v0; game_state = kGameState_9_HitDoorBlock; return 0; } } uint8 BlockColl_Vert_Door(void) { // 0x9493CE door_transition_function = FUNC16(DoorTransitionFunction_HandleElevator); door_bts = BTS[cur_block_index]; uint16 v0 = *(uint16 *)RomPtr_8F(door_list_pointer + 2 * (door_bts & 0x7Fu)); if (*(int16 *)RomPtr_83(v0) >= 0) { if (samus_pose < kPose_09_MoveR_NoAim) elevator_flags = 1; return BlockColl_Vert_SolidShootGrappleBlock(); } else { door_def_ptr = v0; game_state = kPose_09_MoveR_NoAim; return 0; } } uint8 BlockReact_HorizExt(void) { // 0x949411 uint8 t = BTS[cur_block_index]; if (t) { cur_block_index += (int8)t; return 0xff; // special } return 0; } uint8 BlockReact_VertExt(void) { // 0x949447 uint16 v0; if (BTS[cur_block_index]) { if ((BTS[cur_block_index] & 0x80) != 0) { temp_collision_DD4 = BTS[cur_block_index] | 0xFF00; v0 = cur_block_index; do { v0 -= room_width_in_blocks; ++temp_collision_DD4; } while (temp_collision_DD4); } else { temp_collision_DD4 = BTS[cur_block_index]; v0 = cur_block_index; do { v0 += room_width_in_blocks; --temp_collision_DD4; } while (temp_collision_DD4); } cur_block_index = v0; return 0xff; // special } return 0; } void Samus_GetYposSpan(void) { // 0x949495 R26_ = (samus_y_pos - samus_y_radius) & 0xFFF0; R26_ = (uint16)(samus_y_radius + samus_y_pos - 1 - R26_) >> 4; R28_ = R26_; } void Samus_GetXposSpan(void) { // 0x9494B5 R26_ = (samus_x_pos - samus_x_radius) & 0xFFF0; R26_ = (uint16)(samus_x_radius + samus_x_pos - 1 - R26_) >> 4; R28_ = R26_; } static Func_U8 *const kBlockColl_Horiz_CheckColl[16] = { // 0x949515 ClearCarry_4, BlockColl_Horiz_Slope, ClearCarry_5, BlockColl_Horiz_SpecialAir, ClearCarry_4, BlockReact_HorizExt, ClearCarry_4, BlockColl_Horiz_BombableAir, BlockColl_Horiz_SolidShootGrappleBlock, BlockColl_Horiz_Door, BlockColl_Horiz_SpikeBlock, BlockColl_Horiz_SpecialBlock, BlockColl_Horiz_SolidShootGrappleBlock, BlockReact_VertExt, BlockColl_Horiz_SolidShootGrappleBlock, BlockColl_Horiz_BombBlock, }; static Func_U8 *const kBlockColl_Vert_CheckColl[16] = { ClearCarry_4, BlockColl_Vert_Slope, BlockColl_Vert_SpikeAir, BlockColl_Vert_SpecialAir, ClearCarry_4, BlockReact_HorizExt, ClearCarry_4, BlockColl_Vert_BombableAir, BlockColl_Vert_SolidShootGrappleBlock, BlockColl_Vert_Door, BlockColl_Vert_SpikeBlock, BlockColl_Vert_SpecialBlock, BlockColl_Vert_SolidShootGrappleBlock, BlockReact_VertExt, BlockColl_Vert_SolidShootGrappleBlock, BlockColl_Vert_BombBlock, }; uint8 BlockColl_Horiz_CheckColl(uint16 k) { uint8 rv; cur_block_index = k >> 1; do { rv = kBlockColl_Horiz_CheckColl[(level_data[cur_block_index] & 0xF000) >> 12](); } while (rv & 0x80); return rv; } uint8 BlockColl_Vert_CheckColl(uint16 k) { // 0x94952C uint8 rv; cur_block_index = k >> 1; do { rv = kBlockColl_Vert_CheckColl[(level_data[cur_block_index] & 0xF000) >> 12](); } while (rv & 0x80); return rv; } uint8 BlockColl_Handle_Horiz(void) { // 0x949543 Samus_GetYposSpan(); uint16 prod = Mult8x8((uint16)(samus_y_pos - samus_y_radius) >> 4, room_width_in_blocks); uint16 v1; R22_ = R20_ + samus_x_subpos; uint16 v0 = R18_ + __CFADD__uint16(R20_, samus_x_subpos) + samus_x_pos; R24_ = v0; if ((R18_ & 0x8000u) == 0) v1 = samus_x_radius + v0 - 1; else v1 = v0 - samus_x_radius; R32 = v1; uint16 v2 = 2 * (prod + (v1 >> 4)); while (!(BlockColl_Horiz_CheckColl(v2) & 1)) { v2 += room_width_in_blocks + room_width_in_blocks; if ((--R26_ & 0x8000u) != 0) return 0; } return 1; } uint8 BlockColl_Handle_Vert_LeftToRight(void) { // 0x94959E int16 v2; Samus_GetXposSpan(); R22_ = R20_ + samus_y_subpos; uint16 v0 = R18_ + __CFADD__uint16(R20_, samus_y_subpos) + samus_y_pos, v1; R24_ = v0; if ((R18_ & 0x8000u) == 0) v1 = samus_y_radius + v0 - 1; else v1 = v0 - samus_y_radius; R32 = v1; uint16 prod = Mult8x8(v1 >> 4, room_width_in_blocks); v2 = (uint16)(samus_x_pos - samus_x_radius) >> 4; cur_block_index = prod + v2; for (int i = 2 * cur_block_index; !(BlockColl_Vert_CheckColl(i) & 1); i += 2) { if ((--R26_ & 0x8000u) != 0) return 0; } return 1; } uint8 BlockColl_Handle_Vert_RightToLeft(void) { // 0x9495F5 int16 v2; Samus_GetXposSpan(); R26_ = 0; R22_ = R20_ + samus_y_subpos; uint16 v0 = R18_ + __CFADD__uint16(R20_, samus_y_subpos) + samus_y_pos, v1; R24_ = v0; if ((R18_ & 0x8000u) == 0) v1 = samus_y_radius + v0 - 1; else v1 = v0 - samus_y_radius; R32 = v1; uint16 prod = Mult8x8(v1 >> 4, room_width_in_blocks); v2 = (uint16)(samus_x_radius + samus_x_pos - 1) >> 4; cur_block_index = prod + v2; for (int i = 2 * cur_block_index; !(BlockColl_Vert_CheckColl(i) & 1); i -= 2) { if (R28_ < ++R26_) return 0; } return 1; } void AbsoluteValueOfInt32(void) { // 0x949653 if ((R18_ & 0x8000u) != 0) { R18_ = ~R18_; bool v0 = R20_ == 0; R20_ = -R20_; if (v0) ++R18_; } } void AbsoluteValueOfInt32_0(void) { // 0x949669 if ((R18_ & 0x8000u) != 0) { R18_ = ~R18_; bool v0 = R20_ == 0; R20_ = -R20_; if (v0) ++R18_; } } uint8 WallJumpBlockCollDetect(void) { // 0x94967F samus_collision_direction |= 0xFu; flag_samus_in_quicksand = 0; if (BlockColl_Handle_Horiz()) { AbsoluteValueOfInt32(); samus_collision_flag = 1; return 1; } else { AbsoluteValueOfInt32(); samus_collision_flag = 0; return 0; } } uint8 Samus_CollDetectChangedPose(void) { // 0x9496AB if ((abs16(R18_) & 0xFFF8) == 0) return CollDetectDueToPoseChange_SingleBlock(); uint16 v3 = R18_; uint16 v2 = R20_; R18_ = R18_ & 0xFFF0 | 8; R20_ = 0; uint8 v1 = CollDetectDueToPoseChange_SingleBlock(); if (v1) return v1; R20_ = v2; R18_ = v3; return CollDetectDueToPoseChange_SingleBlock(); } uint8 CollDetectDueToPoseChange_SingleBlock(void) { // 0x9496E3 char v0; // cf samus_collision_direction |= 0xFu; flag_samus_in_quicksand = 0; if (!(nmi_frame_counter_word & 1)) { v0 = BlockColl_Handle_Vert_LeftToRight(); if (!v0) goto LABEL_6; if (v0) { LABEL_5: AbsoluteValueOfInt32_0(); samus_collision_flag = 1; return 1; } } if (BlockColl_Handle_Vert_RightToLeft()) goto LABEL_5; LABEL_6: AbsoluteValueOfInt32_0(); samus_collision_flag = 0; return 0; } uint8 Samus_MoveRight_NoSolidColl(void) { // 0x94971E if (__PAIR32__(R20_, R18_) && (flag_samus_in_quicksand = 0, BlockColl_Handle_Horiz())) { bool v0 = __CFADD__uint16(R20_, samus_x_subpos); samus_x_subpos += R20_; samus_x_pos += R18_ + v0; samus_collision_flag = 1; return 1; } else { bool v0 = __CFADD__uint16(R20_, samus_x_subpos); samus_x_subpos += R20_; samus_x_pos += R18_ + v0; samus_collision_flag = 0; return 0; } } uint8 Samus_MoveDown_NoSolidColl(void) { // 0x949763 if (__PAIR32__(R20_, R18_)) { samus_pos_adjusted_by_slope_flag = 0; flag_samus_in_quicksand = 0; if (!(nmi_frame_counter_word & 1)) { bool v0; v0 = BlockColl_Handle_Vert_LeftToRight(); if (!v0) goto LABEL_8; if (v0) { LABEL_6: v0 = __CFADD__uint16(R20_, samus_y_subpos); samus_y_subpos += R20_; samus_y_pos += R18_ + v0; LABEL_7: samus_collision_flag = 1; return 1; } } if (BlockColl_Handle_Vert_RightToLeft()) goto LABEL_6; } LABEL_8:; bool v0 = __CFADD__uint16(R20_, samus_y_subpos); samus_y_subpos += R20_; samus_y_pos += R18_ + v0; if (flag_samus_in_quicksand) goto LABEL_7; samus_collision_flag = 0; return 0; } uint8 BlockInsideReact_Slope(void) { // 0x9497BF return 0; } uint8 BlockInsideReact_ShootableAir(void) { // 0x9497D0 samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; return 0; } void ClearCarry_8(void) { // 0x9497D8 } uint8 MaybeUnused_sub_9497DA(void) { // 0x9497DA ++samus_periodic_damage; samus_x_extra_run_speed = 0; samus_x_base_speed = 0; return 0; } uint8 MaybeUnused_sub_9497F2(void) { // 0x9497F2 if (samus_y_dir == 1) { samus_y_subaccel = 0; samus_y_accel = 2; } else { samus_y_speed = 0; samus_y_subspeed = 0; } return 0; } uint8 ClearCarry_6(void) { // 0x949810 return 0; } uint8 ClearCarry_7(void) { // 0x949812 return 0; } uint8 BlockInsideReact_SpikeAir_BTS1(void) { // 0x949814 ++samus_periodic_damage; samus_x_speed_table_pointer = addr_kSamusSpeedTable_LavaAcid_X; samus_y_subaccel = 0; samus_y_accel = 0; if (samus_y_dir == 1) { samus_y_subaccel = 0; samus_y_accel = 5; } else { samus_y_speed = 0; samus_y_subspeed = 0; extra_samus_y_subdisplacement = 0; extra_samus_y_displacement = 2; } return 0; } void nullsub_165(void) { // 0x9497D7 } void BlockInsideReact_SpikeAir_BTS2(void) { // 0x949866 if (!samus_contact_damage_index && !samus_invincibility_timer) { samus_invincibility_timer = 60; samus_knockback_timer = 10; samus_periodic_damage += 16; knockback_x_dir = ((*(uint16 *)&samus_pose_x_dir ^ 0xC) & 8) != 0; } samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; } static Func_V *const kBlockInsideReact_SpikeAir[16] = { // 0x9498CC ClearCarry_8, ClearCarry_8, BlockInsideReact_SpikeAir_BTS2, nullsub_165, nullsub_165, nullsub_165, nullsub_165, nullsub_165, nullsub_165, nullsub_165, nullsub_165, nullsub_165, nullsub_165, nullsub_165, nullsub_165, nullsub_165, }; uint8 BlockInsideReact_SpikeAir(void) { kBlockInsideReact_SpikeAir[BTS[cur_block_index]](); return 0; } uint8 BlockInsideReact_Special_(void) { // 0x9498DC samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; return 0; } void BlockInsideReact_SpecialAir_Default(void) { // 0x9498E3 samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; } void BlockInsideReact_SpecialAir_8(void) { // 0x9498EA if ((area_index != 3 || CheckBossBitForCurArea(1u) & 1) && !samus_y_speed) { extra_samus_x_subdisplacement = 0; extra_samus_x_displacement = 2; } samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; } void BlockInsideReact_SpecialAir_9(void) { // 0x949910 if ((area_index != 3 || CheckBossBitForCurArea(1u) & 1) && !samus_y_speed) { extra_samus_x_subdisplacement = 0; extra_samus_x_displacement = -2; } samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; } void BlockInsideReact_SpecialAir_10(void) { // 0x949936 extra_samus_x_subdisplacement = 0; extra_samus_x_displacement = 2; samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; } void BlockInsideReact_SpecialAir_11(void) { // 0x949946 extra_samus_x_subdisplacement = 0; extra_samus_x_displacement = -2; samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; } void BlockInsideReact_SpecialAir_70(void) { // 0x949956 if (inside_block_reaction_samus_point == 1) SpawnPLM(addr_kPlmHeader_B6FF); } static const uint16 g_off_949B06[8] = { // 0x949B16 0x9a06, 0x9a26, 0x9a46, 0x9a66, 0x9a86, 0x9aa6, 0x9ac6, 0x9ae6, }; static Func_V *const off_949966[80] = { BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_8, BlockInsideReact_SpecialAir_9, BlockInsideReact_SpecialAir_10, BlockInsideReact_SpecialAir_11, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_70, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, BlockInsideReact_SpecialAir_Default, }; uint8 BlockInsideReact_SpecialAir(void) { int16 v0; v0 = BTS[cur_block_index] << 8; if (v0 < 0) { R34 = g_off_949B06[area_index]; uint8 *v3 = RomPtr_94(R34); SpawnPLM(*(uint16 *)&v3[(2 * (HIBYTE(v0) & 0x7F))]); } else { off_949966[v0 >> 8](); } return 0; } void BlockInsideDetection(void) { // 0x949B60 static Func_U8 *const kSamus_BlockInsideDetection[16] = { BlockInsideReact_ShootableAir, BlockInsideReact_Slope, BlockInsideReact_SpikeAir, BlockInsideReact_SpecialAir, BlockInsideReact_ShootableAir, BlockReact_HorizExt, BlockInsideReact_ShootableAir, BlockInsideReact_ShootableAir, BlockInsideReact_Special_, BlockInsideReact_Special_, BlockInsideReact_Special_, BlockInsideReact_Special_, BlockInsideReact_Special_, BlockReact_VertExt, BlockInsideReact_Special_, BlockInsideReact_Special_, }; *(uint16 *)&samus_x_decel_mult = 0; extra_samus_x_subdisplacement = 0; extra_samus_x_displacement = 0; extra_samus_y_subdisplacement = 0; extra_samus_y_displacement = 0; inside_block_reaction_samus_point = 0; R26_ = samus_x_pos; samus_bottom_boundary_position = samus_y_radius + samus_y_pos - 1; R28_ = samus_y_radius + samus_y_pos - 1; g_word_7E001E = 0; R32 = 0; CalculateBlockAt(); uint8 rv; do { rv = kSamus_BlockInsideDetection[(HIBYTE(level_data[cur_block_index]) & 0xF0) >> 4](); } while (rv & 0x80); inside_block_reaction_samus_point = 1; if (((samus_bottom_boundary_position ^ samus_y_pos) & 0xFFF0) != 0) { R26_ = samus_x_pos; R28_ = samus_y_pos; g_word_7E001E = 0; R32 = 0; CalculateBlockAt(); do { rv = kSamus_BlockInsideDetection[(HIBYTE(level_data[cur_block_index]) & 0xF0) >> 4](); } while (rv & 0x80); } inside_block_reaction_samus_point = 2; if (((samus_bottom_boundary_position ^ (uint16)(samus_y_pos - samus_y_radius)) & 0xFFF0) != 0 && ((samus_y_pos ^ (samus_bottom_boundary_position ^ (uint16)(samus_y_pos - samus_y_radius)) & 0xFFF0) & 0xFFF0) != 0) { R26_ = samus_x_pos; R28_ = samus_y_pos - samus_y_radius; g_word_7E001E = 0; R32 = 0; CalculateBlockAt(); do { rv = kSamus_BlockInsideDetection[(HIBYTE(level_data[cur_block_index]) & 0xF0) >> 4](); } while (rv & 0x80); } } void CalculateBlockAt(void) { // 0x949C1D int16 v0; int16 v1; v0 = g_word_7E001E + R26_; if ((int16)(g_word_7E001E + R26_) >= 0 && sign16(v0 - 4096) && (temp_collision_DD4 = (uint16)(v0 & 0xFFF0) >> 4, v1 = R32 + R28_, (int16)(R32 + R28_) >= 0) && sign16(v1 - 4096)) { uint16 RegWord = (uint16)(v1 & 0xFFF0) >> 4; RegWord = Mult8x8(RegWord, room_width_in_blocks); cur_block_index = temp_collision_DD4 + RegWord; } else { cur_block_index = -1; } } static const uint8 kBlockFunc_9C73_Tab0[36] = { // 0x949C73 3, 20, 0, 10, 40, 1, 5, 30, 0, 10, 40, 1, 20, 80, 0, 20, 80, 1, 20, 80, 0, 20, 80, 1, 30, 100, 0, 30, 100, 1, 30, 100, 0, 30, 100, 1, }; static const int8 kBlockFunc_9C73_Tab1[18] = { 0, 0, 10, 0, 50, 0, 50, 3, 0, -1, 10, 2, 0, -1, 0, -1, 0, -1, }; void BlockFunc_9C73(uint16 v0) { int v1 = v0 >> 1; if ((projectile_type[v1] & 0xF00) != 0) { temp_collision_DD2 = kBlockFunc_9C73_Tab1[(uint16)(2 * (HIBYTE(projectile_type[v1]) & 0xF) + 1)]; } else { R18_ = projectile_type[v1] & 0xF; temp_collision_DD2 = kBlockFunc_9C73_Tab0[(uint16)(R18_ + 2 * R18_ + 2)]; } } void BombOrPowerBomb_Func1(uint16 v0) { // 0x949CAC int16 v2; int16 v3; BlockFunc_9C73(v0); int v1 = v0 >> 1; v2 = projectile_x_pos[v1]; if (v2 >= 0) { R26_ = projectile_x_pos[v1]; if ((int16)(HIBYTE(v2) - room_width_in_scrolls) < 0) { v3 = projectile_y_pos[v1]; if (v3 >= 0) { R28_ = projectile_y_pos[v1]; if ((int16)(HIBYTE(v3) - room_height_in_scrolls) < 0) { g_word_7E001E = 0; R32 = 0; cur_block_index = 0; CalculateBlockAt(); if (temp_collision_DD2 == 2) BlockColl_BombExplosion(v0); else BlockFunc_A06A(v0); } } } } } void BlockColl_BombExplosion(uint16 k) { // 0x949CF4 int16 v2; int v1 = k >> 1; if (!projectile_variables[v1]) { v2 = projectile_type[v1]; if ((v2 & 1) == 0) { projectile_type[v1] = v2 | 1; if (cur_block_index != 0xFFFF) { uint16 v3 = 2 * cur_block_index; BlockBombedReact(2 * cur_block_index); uint16 idx = BlockColl_GetBlockIndexAbove(v3); BlockBombedReact(idx); uint16 idx2 = BlockColl_GetBlockIndexRight(idx); BlockBombedReact(idx2); idx = BlockColl_GetBlockIndexLeft(idx2); BlockBombedReact(idx); idx = BlockColl_GetBlockIndexBelow(idx); BlockBombedReact(idx); } } } } uint16 BlockColl_GetBlockIndexAbove(uint16 k) { // 0x949D34 return k - room_width_in_blocks - room_width_in_blocks; } uint16 BlockColl_GetBlockIndexRight(uint16 k) { // 0x949D3E return room_width_in_blocks + room_width_in_blocks + k + 1 + 1; } uint16 BlockColl_GetBlockIndexLeft(uint16 k) { // 0x949D49 return k - 4; } uint16 BlockColl_GetBlockIndexBelow(uint16 k) { // 0x949D4E return room_width_in_blocks + room_width_in_blocks + k + 1 + 1; } uint8 ClearCarry_9(void) { // 0x949D59 return 0; } uint8 SetCarry_0(void) { // 0x949D5B return 1; } uint8 sub_949D5D(void) { // 0x949D5D if ((BTS[cur_block_index] & 0x1Fu) < 5) return 1; else return BlockShotReactVert_Slope_NonSquare() & 1; } uint8 BlockBombedReact_Special(void) { // 0x949D71 int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) != 0) { uint16 *kBlockBombedReact_Region_Plm = (uint16 *)RomPtr_94(0x9e44); R18_ = kBlockBombedReact_Region_Plm[area_index]; uint8 *v2 = RomPtr_94(R18_); SpawnPLM(*(uint16 *)&v2[(uint16)(2 * (v0 & 0x7F))]); } else { uint16 *kBlockBombedReact_Special_Plm = (uint16 *)RomPtr_94(0x9dA4); SpawnPLM(kBlockBombedReact_Special_Plm[v0]); } return 1; } uint8 BlockReact_ShootableAir(void) { // 0x949E55 int16 v0; uint16 *kBlockShotBombedReactionShootablePlm = (uint16 *)RomPtr_94(0x9ea6); v0 = BTS[cur_block_index]; if ((v0 & 0x80) == 0) SpawnPLM(kBlockShotBombedReactionShootablePlm[v0]); return 0; } uint8 BlockReact_Shootable(void) { // 0x949E73 int16 v0; v0 = BTS[cur_block_index]; if ((v0 & 0x80) != 0) { uint16 *kBlockShotBombGrappleReaction_ShootableBlock_RegionPlm = (uint16 *)RomPtr_94(0x9FC6); R18_ = kBlockShotBombGrappleReaction_ShootableBlock_RegionPlm[area_index]; uint8 *v2 = RomPtr_94(R18_); SpawnPLM(*(uint16 *)&v2[(uint16)(2 * (v0 & 0x7F))]); } else { uint16 *kBlockShotBombedReactionShootablePlm = (uint16 *)RomPtr_94(0x9ea6); SpawnPLM(kBlockShotBombedReactionShootablePlm[v0]); } return 1; } uint8 BlockReact_BombableAir(void) { // 0x949FD6 int16 v0; uint16 *kBlockShotBombGrappleReact_BombableBlockPlm = (uint16 *)RomPtr_94(0xA012); v0 = BTS[cur_block_index]; if ((v0 & 0x80) == 0) SpawnPLM(kBlockShotBombGrappleReact_BombableBlockPlm[v0]); return 0; } uint8 BlockReact_BombableBlock(void) { // 0x949FF4 int16 v0; uint16 *kBlockShotBombGrappleReact_BombableBlockPlm = (uint16 *)RomPtr_94(0xA012); v0 = BTS[cur_block_index]; if ((v0 & 0x80) == 0) SpawnPLM(kBlockShotBombGrappleReact_BombableBlockPlm[v0]); return 1; } static Func_U8 *const kBlockBombedReact[16] = { // 0x94A052 ClearCarry_9, ClearCarry_9, ClearCarry_9, ClearCarry_9, BlockReact_ShootableAir, BlockReact_HorizExt, ClearCarry_9, BlockReact_BombableAir, SetCarry_0, SetCarry_0, SetCarry_0, BlockBombedReact_Special, BlockReact_Shootable, BlockReact_VertExt, SetCarry_0, BlockReact_BombableBlock, }; void BlockBombedReact(uint16 v0) { cur_block_index = v0 >> 1; while (kBlockBombedReact[(level_data[cur_block_index] & 0xF000) >> 12]() & 0x80) {} } void BlockFunc_A06A(uint16 k) { // 0x94A06A int16 v2; int16 v3; int v1 = k >> 1; v2 = projectile_variables[v1]; if (v2) { if (v2 < 0) projectile_variables[v1] = 0; } else { R18_ = HIBYTE(power_bomb_explosion_radius); R20_ = (uint16)(HIBYTE(power_bomb_explosion_radius) + 2 * HIBYTE(power_bomb_explosion_radius)) >> 2; v3 = power_bomb_explosion_x_pos - HIBYTE(power_bomb_explosion_radius); if (v3 < 0) v3 = 0; R22_ = (uint16)v3 >> 4; uint16 v4 = (uint16)(R18_ + power_bomb_explosion_x_pos) >> 4; if (v4 >= room_width_in_blocks) v4 = room_width_in_blocks - 1; R24_ = v4; uint16 v5 = power_bomb_explosion_y_pos - R20_; if ((int16)(power_bomb_explosion_y_pos - R20_) < 0) v5 = 0; R26_ = v5 >> 4; uint16 v6 = (uint16)(R20_ + power_bomb_explosion_y_pos) >> 4; if (v6 >= room_height_in_blocks) v6 = room_height_in_blocks - 1; R28_ = v6; uint16 a = R26_ | ((uint8)R22_ << 8); BlockFunc_A0F4(a); BlockFunc_A11A(a); BlockFunc_A0F4(R28_ | ((uint8)R22_ << 8)); BlockFunc_A11A(R26_ | ((uint8)R24_ << 8)); } } void BlockFunc_A0F4(uint16 a) { // 0x94A0F4 int16 v4; uint16 RegWord = Mult8x8(a, room_width_in_blocks); uint16 v3 = 2 * (RegWord + HIBYTE(a)); v4 = R24_ - R22_; do { BlockBombedReact(v3); v3 += 2; --v4; } while (v4 >= 0); } void BlockFunc_A11A(uint16 a) { // 0x94A11A int16 v4; uint16 RegWord = Mult8x8(a, room_width_in_blocks); uint16 v3 = 2 * (RegWord + HIBYTE(a)); v4 = R28_ - R26_; do { BlockBombedReact(v3); v3 += room_width_in_blocks + room_width_in_blocks; --v4; } while (v4 >= 0); } uint8 BlockShotReactHoriz_Slope(void) { // 0x94A147 if ((BTS[cur_block_index] & 0x1Fu) < 5) return BlockShotReactVert_Slope_Square(BTS[cur_block_index] & 0x1F, cur_block_index); else return BlockShotReactVert_Slope_NonSquare(); } uint8 SetCarry_1(void) { // 0x94A15C return 1; } uint8 BlockShotReactVert_Slope(void) { // 0x94A15E if ((BTS[cur_block_index] & 0x1Fu) < 5) return BlockShotReactHoriz_Slope_Square(BTS[cur_block_index] & 0x1F, cur_block_index); else return BlockShotReactHoriz_Slope_NonSquare(); } uint8 SetCarry_2(void) { // 0x94A173 return 1; } uint8 BlockShotReactHoriz(uint16 k) { // 0x94A1B5 static Func_U8 *const kBlockShotReactHoriz[16] = { ClearCarry_9, BlockShotReactHoriz_Slope, ClearCarry_9, ClearCarry_9, BlockReact_ShootableAir, BlockReact_HorizExt, ClearCarry_9, BlockReact_BombableAir, SetCarry_0, SetCarry_0, SetCarry_0, SetCarry_0, BlockReact_Shootable, BlockReact_VertExt, SetCarry_0, BlockReact_BombableBlock, }; uint8 v1 = k >= room_size_in_blocks; if (k < room_size_in_blocks) { cur_block_index = k >> 1; do { v1 = kBlockShotReactHoriz[(level_data[cur_block_index] & 0xF000) >> 12](); } while (v1 & 0x80); if (v1) --R40; } return v1; } uint8 BlockShotReactVert(uint16 k) { // 0x94A1D6 static Func_U8 *const kBlockShotReactVert[16] = { ClearCarry_9, BlockShotReactVert_Slope, ClearCarry_9, ClearCarry_9, BlockReact_ShootableAir, BlockReact_HorizExt, ClearCarry_9, BlockReact_BombableAir, SetCarry_0, SetCarry_0, SetCarry_0, SetCarry_0, BlockReact_Shootable, BlockReact_VertExt, SetCarry_0, BlockReact_BombableBlock, }; uint8 v1 = k >= room_size_in_blocks; if (k < room_size_in_blocks) { cur_block_index = k >> 1; do { v1 = kBlockShotReactVert[(level_data[cur_block_index] & 0xF000) >> 12](); } while (v1 & 0x80); if (v1) --R40; } return v1; } void BlockGetSomePos1(uint16 k) { // 0x94A1F7 int v1 = k >> 1; R38 = (projectile_y_pos[v1] - projectile_y_radius[v1]) & 0xFFF0; R38 = (uint16)(projectile_y_radius[v1] + projectile_y_pos[v1] - 1 - R38) >> 4; R26_ = R38; R40 = R38; } void BlockGetSomePos2(uint16 k) { // 0x94A219 int v1 = k >> 1; R38 = (projectile_x_pos[v1] - projectile_x_radius[v1]) & 0xFFF0; R38 = (uint16)(projectile_x_radius[v1] + projectile_x_pos[v1] - 1 - R38) >> 4; R26_ = R38; R40 = R38; } uint8 BlockCollNoWaveBeamHoriz(uint16 k) { // 0x94A23B int16 v2; g_word_7E001E = 0; R18_ = 0; R20_ = 0; int v1 = k >> 1; v2 = projectile_bomb_x_speed[v1]; if (v2 < 0) --R20_; *(uint16 *)((char *)&R18_ + 1) = v2; BlockGetSomePos1(k); uint16 prod = Mult8x8((uint16)(projectile_y_pos[v1] - projectile_y_radius[v1]) >> 4, room_width_in_blocks); uint16 v3 = projectile_bomb_x_subpos[v1]; bool v4 = __CFADD__uint16(R18_, v3); uint16 v5 = R18_ + v3; projectile_bomb_x_subpos[v1] = v5; R22_ = v5; uint16 v6 = R20_ + v4 + projectile_x_pos[v1], v7; projectile_x_pos[v1] = v6; R24_ = v6; if ((R20_ & 0x8000u) != 0) v7 = v6 - projectile_x_radius[v1]; else v7 = projectile_x_radius[v1] + v6 - 1; R28_ = v7; uint16 v8 = 2 * (prod + (v7 >> 4)); if (!sign16(R38 - 16) || (int16)(HIBYTE(R28_) - room_width_in_scrolls) >= 0) return 0; do { BlockShotReactHoriz(v8); v8 += room_width_in_blocks + room_width_in_blocks; --R38; } while ((R38 & 0x8000u) == 0); if ((R40 & 0x8000u) == 0) return 0; KillProjectile(k); return 1; } uint8 BlockCollNoWaveBeamVert(uint16 k) { // 0x94A2CA int16 v2; int16 v8; int16 v9; g_word_7E001E = 0; R18_ = 0; R20_ = 0; int v1 = k >> 1; v2 = projectile_bomb_y_speed[v1]; if (v2 < 0) --R20_; *(uint16 *)((char *)&R18_ + 1) = v2; BlockGetSomePos2(k); uint16 v3 = projectile_bomb_y_subpos[v1]; bool v4 = __CFADD__uint16(R18_, v3); uint16 v5 = R18_ + v3; projectile_bomb_y_subpos[v1] = v5; R22_ = v5; uint16 v6 = R20_ + v4 + projectile_y_pos[v1], v7; projectile_y_pos[v1] = v6; R24_ = v6; if ((R20_ & 0x8000u) != 0) v7 = v6 - projectile_y_radius[v1]; else v7 = projectile_y_radius[v1] + v6 - 1; R28_ = v7; v8 = (uint16)(projectile_x_pos[v1] - projectile_x_radius[v1]) >> 4; v9 = 2 * (Mult8x8(v7 >> 4, room_width_in_blocks) + v8); if (!sign16(R38 - 16) || (int16)(HIBYTE(R28_) - room_height_in_scrolls) >= 0) return 0; do { BlockShotReactVert(v9); v9 += 2; --R38; } while ((R38 & 0x8000u) == 0); if ((R40 & 0x8000u) == 0) return 0; KillProjectile(k); return 1; } uint8 BlockCollWaveBeamHoriz(uint16 k) { // 0x94A352 int16 v2; int16 v8; char v9; int16 v10; g_word_7E001E = 0; R18_ = 0; R20_ = 0; int v1 = k >> 1; v2 = projectile_bomb_x_speed[v1]; if (v2 < 0) --R20_; *(uint16 *)((char *)&R18_ + 1) = v2; BlockGetSomePos1(k); uint16 prod = Mult8x8((uint16)(projectile_y_pos[v1] - projectile_y_radius[v1]) >> 4, room_width_in_blocks); uint16 v3 = projectile_bomb_x_subpos[v1]; bool v4 = __CFADD__uint16(R18_, v3); uint16 v5 = R18_ + v3; projectile_bomb_x_subpos[v1] = v5; R22_ = v5; uint16 v6 = R20_ + v4 + projectile_x_pos[v1], v7; projectile_x_pos[v1] = v6; R24_ = v6; if ((R20_ & 0x8000u) != 0) v7 = v6 - projectile_x_radius[v1]; else v7 = projectile_x_radius[v1] + v6 - 1; R28_ = v7; v8 = 2 * (prod + (v7 >> 4)); if (sign16(R38 - 16)) { v9 = HIBYTE(projectile_y_pos[v1]); if (v9 >= 0 && (int16)((uint8)v9 - room_height_in_scrolls) < 0 && (int16)(HIBYTE(R28_) - room_width_in_scrolls) < 0) { v10 = v8; do { BlockShotReactHoriz(v10); v10 += room_width_in_blocks + room_width_in_blocks; --R38; } while ((R38 & 0x8000u) == 0); } } return 0; } uint8 BlockCollWaveBeamVert(uint16 k) { // 0x94A3E4 int16 v2; int16 v8; int16 v9; char v10; int16 v11; g_word_7E001E = 0; R18_ = 0; R20_ = 0; int v1 = k >> 1; v2 = projectile_bomb_y_speed[v1]; if (v2 < 0) --R20_; *(uint16 *)((char *)&R18_ + 1) = v2; BlockGetSomePos2(k); uint16 v3 = projectile_bomb_y_subpos[v1]; bool v4 = __CFADD__uint16(R18_, v3); uint16 v5 = R18_ + v3; projectile_bomb_y_subpos[v1] = v5; R22_ = v5; uint16 v6 = R20_ + v4 + projectile_y_pos[v1], v7; projectile_y_pos[v1] = v6; R24_ = v6; if ((R20_ & 0x8000u) != 0) v7 = v6 - projectile_y_radius[v1]; else v7 = projectile_y_radius[v1] + v6 - 1; R28_ = v7; uint16 prod = Mult8x8(v7 >> 4, room_width_in_blocks); v8 = (uint16)(projectile_x_pos[v1] - projectile_x_radius[v1]) >> 4; v9 = 2 * (prod + v8); if (sign16(R38 - 16)) { v10 = HIBYTE(projectile_x_pos[v1]); if (v10 >= 0 && (int16)((uint8)v10 - room_width_in_scrolls) < 0 && (int16)(HIBYTE(R28_) - room_height_in_scrolls) < 0) { v11 = v9; do { BlockShotReactVert(v11); v11 += 2; --R38; } while ((R38 & 0x8000u) == 0); } } return 0; } uint8 BlockCollMissileHoriz(uint16 k) { // 0x94A46F int16 v2; g_word_7E001E = 1; R38 = 0; R26_ = 0; R18_ = 0; R20_ = 0; int v1 = k >> 1; v2 = projectile_bomb_x_speed[v1]; if (v2 < 0) --R20_; *(uint16 *)((char *)&R18_ + 1) = v2; uint16 prod = Mult8x8(projectile_y_pos[v1] >> 4, room_width_in_blocks); uint16 v3 = projectile_bomb_x_subpos[v1]; bool v4 = __CFADD__uint16(R18_, v3); uint16 v5 = R18_ + v3; projectile_bomb_x_subpos[v1] = v5; R22_ = v5; uint16 v6 = R20_ + v4 + projectile_x_pos[v1]; projectile_x_pos[v1] = v6; R24_ = v6; R28_ = v6; uint16 v7 = 2 * (prod + (v6 >> 4)); if ((int16)(HIBYTE(R24_) - room_width_in_scrolls) >= 0 || !(BlockShotReactHoriz(v7) & 1)) return 0; KillProjectile(k); return 1; } uint8 BlockCollMissileVert(uint16 k) { // 0x94A4D9 int16 v2; int16 v7; g_word_7E001E = 1; R38 = 0; R26_ = 0; R18_ = 0; R20_ = 0; int v1 = k >> 1; v2 = projectile_bomb_y_speed[v1]; if (v2 < 0) --R20_; *(uint16 *)((char *)&R18_ + 1) = v2; uint16 v3 = projectile_bomb_y_subpos[v1]; bool v4 = __CFADD__uint16(R18_, v3); uint16 v5 = R18_ + v3; projectile_bomb_y_subpos[v1] = v5; R22_ = v5; uint16 v6 = R20_ + v4 + projectile_y_pos[v1]; projectile_y_pos[v1] = v6; R24_ = v6; R28_ = v6; uint16 prod = Mult8x8(v6 >> 4, room_width_in_blocks); v7 = projectile_x_pos[v1] >> 4; uint16 v8 = 2 * (prod + v7); if ((int16)(HIBYTE(R24_) - room_height_in_scrolls) >= 0 || !(BlockShotReactVert(v8) & 1)) return 0; KillProjectile(k); return 1; } uint8 BlockShotReactVert_Slope_NonSquare(void) { // 0x94A543 int16 v2; uint16 v0 = cur_block_index; uint16 v1 = projectile_index; uint16 div = SnesDivide(cur_block_index, room_width_in_blocks); v2 = projectile_y_pos[v1 >> 1] >> 4; if (v2 == div) return BlockShotReact_Slope_NonSquare(v1, v0) & 1; else return 0; } uint8 BlockShotReactHoriz_Slope_NonSquare(void) { // 0x94A569 int16 v2; uint16 v0 = cur_block_index; uint16 v1 = projectile_index; uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); v2 = projectile_x_pos[v1 >> 1] >> 4; if (v2 == mod) return BlockShotReact_Slope_NonSquare(v1, v0) & 1; else return 0; } uint8 BlockShotReact_Slope_NonSquare(uint16 j, uint16 k) { // 0x94A58F int16 v3; int16 v5; uint16 v2; temp_collision_DD6 = 16 * (BTS[k] & 0x1F); if ((BTS[k] & 0x40) != 0) v2 = projectile_x_pos[j >> 1] ^ 0xF; else v2 = projectile_x_pos[j >> 1]; uint16 v6 = temp_collision_DD6 + (v2 & 0xF); if (!(BTS[k] & 0x80)) { temp_collision_DD4 = projectile_y_pos[j >> 1] & 0xF; v5 = kAlignYPos_Tab0[v6] & 0x1F; if ((int16)(v5 - temp_collision_DD4) < 0 || v5 == temp_collision_DD4) { R38 = 0; R40 = 0; return 1; } else { return 0; } } else { temp_collision_DD4 = projectile_y_pos[j >> 1] & 0xF ^ 0xF; v3 = kAlignYPos_Tab0[v6] & 0x1F; if ((int16)(v3 - temp_collision_DD4) < 0 || v3 == temp_collision_DD4) { R38 = 0; R40 = 0; return 1; } else { return 0; } } } uint8 BlockCollSpreadBomb(uint16 k) { // 0x94A621 static Func_U8 *const kBlockCollSpreadBomb[16] = { ClearCarry_9, sub_949D5D, ClearCarry_9, ClearCarry_9, SetCarry_0, BlockReact_HorizExt, ClearCarry_9, ClearCarry_9, SetCarry_0, SetCarry_0, SetCarry_0, SetCarry_0, SetCarry_0, BlockReact_VertExt, SetCarry_0, SetCarry_0, }; int v1 = k >> 1; R26_ = projectile_x_pos[v1]; R28_ = projectile_y_pos[v1]; g_word_7E001E = 0; R32 = 0; cur_block_index = 0; CalculateBlockAt(); if (!projectile_variables[v1]) { BlockColl_BombExplosion(k); return 0; } if (cur_block_index == 0xFFFF) return 1; uint8 rv; do { rv = kBlockCollSpreadBomb[(level_data[cur_block_index] & 0xF000) >> 12](); } while (rv & 0x80); return rv; } uint8 BlockShotReactVert_Slope_Square(uint16 a, uint16 k) { // 0x94A66A temp_collision_DD4 = 4 * a; temp_collision_DD6 = BTS[k] >> 6; uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R28_ & 8) >> 3)); if (!g_word_7E001E) { if (!R26_) { int v3 = projectile_index >> 1; if (((projectile_y_pos[v3] - projectile_y_radius[v3]) & 8) != 0 || !kTab948E54[v2]) { uint16 v4 = v2 ^ 2; if (((LOBYTE(projectile_y_radius[v3]) + LOBYTE(projectile_y_pos[v3]) - 1) & 8) == 0 || !kTab948E54[v4]) { return 0; } } return 1; } if (R38) { if (R38 == R26_ && ((projectile_y_pos[projectile_index >> 1] - projectile_y_radius[projectile_index >> 1]) & 8) != 0) { return kTab948E54[v2 ^ 2] != 0; } } else if (((LOBYTE(projectile_y_radius[projectile_index >> 1]) + LOBYTE(projectile_y_pos[projectile_index >> 1]) - 1) & 8) == 0) { return kTab948E54[v2] != 0; } if (kTab948E54[v2] != 0) return 1; return kTab948E54[v2 ^ 2] != 0; } if ((projectile_y_pos[projectile_index >> 1] & 8) != 0) v2 ^= 2u; return kTab948E54[v2] != 0; } uint8 BlockShotReactHoriz_Slope_Square(uint16 a, uint16 k) { // 0x94A71A temp_collision_DD4 = 4 * a; temp_collision_DD6 = BTS[k] >> 6; uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R28_ & 8) >> 2)); if (!g_word_7E001E) { if (!R26_) { int v3 = projectile_index >> 1; if (((projectile_x_pos[v3] - projectile_x_radius[v3]) & 8) != 0 || kTab948E54[v2] == 0) { uint16 v4 = v2 ^ 1; if (((LOBYTE(projectile_x_radius[v3]) + LOBYTE(projectile_x_pos[v3]) - 1) & 8) == 0 || kTab948E54[v4] == 0) { return 0; } } return 1; } if (R38) { if (R38 == R26_ && ((projectile_x_pos[projectile_index >> 1] - projectile_x_radius[projectile_index >> 1]) & 8) != 0) { return kTab948E54[v2 ^ 1] != 0; } } else if (((LOBYTE(projectile_x_radius[projectile_index >> 1]) + LOBYTE(projectile_x_pos[projectile_index >> 1]) - 1) & 8) == 0) { return kTab948E54[v2] != 0; } if (kTab948E54[v2] != 0) return 1; return kTab948E54[v2 ^ 1] != 0; } if ((projectile_x_pos[projectile_index >> 1] & 8) != 0) v2 ^= 1u; return kTab948E54[v2] != 0; } uint8 ClearCarryZero(void) { // 0x94A7C9 return 0; } uint8 ClearCarrySetZero(void) { // 0x94A7CD return 1; } uint8 BlockReactGrapple_GrappleBlock(void) { // 0x94A7D1 static const uint16 kBlockReactGrapple_GrappleBlockPlm[4] = { 0xd0d8, 0xd0dc, 0xd0e0, 0xd0d8, }; char v0; grapple_beam_flags &= ~0x8000u; v0 = BTS[cur_block_index]; if (v0 < 0) return 0; else return SpawnPLM(kBlockReactGrapple_GrappleBlockPlm[v0 & 0x7F]); } uint8 BlockReactGrapple_SpikeBlock(void) { // 0x94A7FD static const uint16 kBlockReactGrapple_SpikeBlockPlm[16] = { 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e8, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, }; char v0; v0 = BTS[cur_block_index]; if (v0 < 0) return 0; else return SpawnPLM(kBlockReactGrapple_SpikeBlockPlm[v0 & 0x7F]); } uint8 BlockCollGrappleBeam(void) { // 0x94A85B uint8 result; *(uint16 *)((char *)&grapple_beam_tmpD82 + 1) = grapple_beam_extension_x_velocity; *(uint32 *)&grapple_beam_tmpD82 >>= 2; if ((grapple_beam_extension_x_velocity & 0x8000u) != 0) grapple_beam_tmpD84 |= 0xFFC0u; *(uint16 *)((char *)&grapple_beam_y_quarter_subvel + 1) = grapple_beam_extension_y_velocity; *(uint32 *)&grapple_beam_y_quarter_subvel >>= 2; if ((grapple_beam_extension_y_velocity & 0x8000u) != 0) grapple_beam_y_quarter_vel |= 0xFFC0u; grapple_beam_tmpD8A = 4; while (1) { uint16 v0 = (__PAIR32__(grapple_beam_tmpD84, grapple_beam_tmpD82) + __PAIR32__(grapple_beam_end_x_offset, grapple_beam_end_x_suboffset)) >> 16; grapple_beam_end_x_suboffset += grapple_beam_tmpD82; grapple_beam_end_x_offset = v0; uint16 v1 = (__PAIR32__(grapple_beam_y_quarter_vel, grapple_beam_y_quarter_subvel) + __PAIR32__(grapple_beam_end_y_offset, grapple_beam_end_y_suboffset)) >> 16; grapple_beam_end_y_suboffset += grapple_beam_y_quarter_subvel; grapple_beam_end_y_offset = v1; grapple_beam_end_x_subpos = grapple_beam_end_x_suboffset + samus_x_subpos; grapple_beam_end_x_pos = grapple_beam_origin_x_offset + ((__PAIR32__(grapple_beam_end_x_offset, grapple_beam_end_x_suboffset) + __PAIR32__(samus_x_pos, samus_x_subpos)) >> 16); grapple_beam_end_y_subpos = grapple_beam_end_y_suboffset + samus_y_subpos; grapple_beam_end_y_pos = grapple_beam_origin_y_offset + ((__PAIR32__(v1, grapple_beam_end_y_suboffset) + __PAIR32__(samus_y_pos, samus_y_subpos)) >> 16); result = BlockReactGrapple(); if ((result & 0x40) != 0 && (result & 1) != 0) break; if (!--grapple_beam_tmpD8A) return result; } grapple_beam_end_x_pos = grapple_beam_end_x_pos & 0xFFF0 | 8; grapple_beam_end_y_pos = grapple_beam_end_y_pos & 0xFFF0 | 8; return result; } uint8 BlockReactGrapple(void) { // 0x94A91F int16 v0; static Func_U8 *const kBlockReactGrapple[16] = { ClearCarryZero, ClearCarrySetZero, ClearCarryZero, ClearCarryZero, BlockReact_ShootableAir, BlockReact_HorizExt, ClearCarryZero, BlockReact_BombableAir, ClearCarrySetZero, ClearCarrySetZero, BlockReactGrapple_SpikeBlock, ClearCarrySetZero, BlockReact_Shootable, BlockReact_VertExt, BlockReactGrapple_GrappleBlock, BlockReact_BombableBlock, }; uint16 prod = Mult8x8(grapple_beam_end_y_pos >> 4, room_width_in_blocks); v0 = grapple_beam_end_x_pos >> 4; cur_block_index = prod + v0; uint8 rv; do { rv = kBlockReactGrapple[(level_data[cur_block_index] & 0xF000) >> 12](); } while (rv & 0x80); return rv; } const int16 kSinCosTable8bit_Sext[320] = { // 0x94A957 -256, -255, -255, -255, -254, -254, -253, -252, -251, -249, -248, -246, -244, -243, -241, -238, -236, -234, -231, -228, -225, -222, -219, -216, -212, -209, -205, -201, -197, -193, -189, -185, -181, -176, -171, -167, -162, -157, -152, -147, -142, -136, -131, -126, -120, -115, -109, -103, -97, -92, -86, -80, -74, -68, -62, -56, -49, -43, -37, -31, -25, -18, -12, -6, 0, 6, 12, 18, 25, 31, 37, 43, 49, 56, 62, 68, 74, 80, 86, 92, 97, 103, 109, 115, 120, 126, 131, 136, 142, 147, 152, 157, 162, 167, 171, 176, 181, 185, 189, 193, 197, 201, 205, 209, 212, 216, 219, 222, 225, 228, 231, 234, 236, 238, 241, 243, 244, 246, 248, 249, 251, 252, 253, 254, 254, 255, 255, 255, 256, 255, 255, 255, 254, 254, 253, 252, 251, 249, 248, 246, 244, 243, 241, 238, 236, 234, 231, 228, 225, 222, 219, 216, 212, 209, 205, 201, 197, 193, 189, 185, 181, 176, 171, 167, 162, 157, 152, 147, 142, 136, 131, 126, 120, 115, 109, 103, 97, 92, 86, 80, 74, 68, 62, 56, 49, 43, 37, 31, 25, 18, 12, 6, 0, -6, -12, -18, -25, -31, -37, -43, -49, -56, -62, -68, -74, -80, -86, -92, -97, -103, -109, -115, -120, -126, -131, -136, -142, -147, -152, -157, -162, -167, -171, -176, -181, -185, -189, -193, -197, -201, -205, -209, -212, -216, -219, -222, -225, -228, -231, -234, -236, -238, -241, -243, -244, -246, -248, -249, -251, -252, -253, -254, -254, -255, -255, -255, -256, -255, -255, -255, -254, -254, -253, -252, -251, -249, -248, -246, -244, -243, -241, -238, -236, -234, -231, -228, -225, -222, -219, -216, -212, -209, -205, -201, -197, -193, -189, -185, -181, -176, -171, -167, -162, -157, -152, -147, -142, -136, -131, -126, -120, -115, -109, -103, -97, -92, -86, -80, -74, -68, -62, -56, -49, -43, -37, -31, -25, -18, -12, -6, }; void BlockFunc_A957(void) { int16 v5; int16 v7; uint16 v0 = grapple_beam_tmpD82, v2, v3; if ((grapple_beam_flags & 0x8000u) == 0) { int v1 = grapple_beam_tmpD82 >> 1; if ((kSinCosTable8bit_Sext[v1 + 64] & 0x8000u) != 0) v2 = grapple_beam_end_x_pos & 0xFFF0 | 7; else v2 = grapple_beam_end_x_pos & 0xFFF0 | 8; grapple_beam_end_x_pos = v2; if ((kSinCosTable8bit_Sext[v1] & 0x8000u) != 0) v3 = grapple_beam_end_y_pos & 0xFFF0 | 7; else v3 = grapple_beam_end_y_pos & 0xFFF0 | 8; grapple_beam_end_y_pos = v3; } WriteReg(WRMPYA, grapple_beam_tmpD84); int v4 = v0 >> 1; v5 = kSinCosTable8bit_Sext[v4 + 64]; uint16 v6, v8; if (v5 < 0) { if (v5 == -256) { v6 = grapple_beam_end_x_pos - grapple_beam_tmpD84; } else { uint16 prod = Mult8x8(grapple_beam_tmpD84, -(int8)v5); v6 = grapple_beam_end_x_pos - (prod >> 8); } } else if (v5 == 256) { v6 = grapple_beam_tmpD84 + grapple_beam_end_x_pos; } else { uint16 prod = Mult8x8(grapple_beam_tmpD84, kSinCosTable8bit_Sext[v4 + 64]); v6 = grapple_beam_end_x_pos + (prod >> 8); } grapple_beam_grapple_start_x = v6; grapple_beam_grapple_start_block_x = (uint8)(v6 >> 4); v7 = kSinCosTable8bit_Sext[v4]; if (v7 < 0) { if (v7 == -256) { v8 = grapple_beam_end_y_pos - grapple_beam_tmpD84; } else { uint16 prod = Mult8x8(grapple_beam_tmpD84, -v7); v8 = grapple_beam_end_y_pos - (prod >> 8); } } else if (v7 == 256) { v8 = grapple_beam_tmpD84 + grapple_beam_end_y_pos; } else { uint16 prod = Mult8x8(grapple_beam_tmpD84, kSinCosTable8bit_Sext[v4]); v8 = grapple_beam_end_y_pos + (prod >> 8); } grapple_beam_grapple_start_y = v8; grapple_beam_grapple_start_block_y = (uint8)(v8 >> 4); } uint8 BlockReact_AA64(void) { // 0x94AA64 static Func_U8 *const kBlockReactLut_AB90[16] = { ClearCarry_10, SetCarry_3, BlockReact_AA64_SpikeAir, ClearCarry_10, ClearCarry_10, BlockReact_HorizExt, ClearCarry_10, ClearCarry_10, SetCarry_3, SetCarry_3, BlockReact_AA64_SpikeBlock, SetCarry_3, SetCarry_3, BlockReact_VertExt, SetCarry_3, SetCarry_3, }; uint16 v0 = grapple_beam_grapple_start_block_x; uint16 RegWord = Mult8x8(grapple_beam_grapple_start_block_y, room_width_in_blocks); cur_block_index = RegWord + v0; uint8 rv; do { rv = kBlockReactLut_AB90[(level_data[cur_block_index] & 0xF000) >> 12](); } while (rv & 0x80); return rv; } uint8 ClearCarry_10(void) { // 0x94AA9A return 0; } uint8 SetCarry_3(void) { // 0x94AA9C return 1; } static const uint16 g_word_94AAD7[16] = { // 0x94AA9E 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static const uint16 g_word_94AAF7[16] = { 0, 0, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; uint8 BlockReact_AA64_SpikeAir(void) { int16 v0; int16 v2; if (!samus_invincibility_timer) { v0 = *(uint16 *)&BTS[cur_block_index]; if (v0 >= 0) { int v1 = v0; if (g_word_94AAF7[v1] | g_word_94AAD7[v1]) { v2 = (g_word_94AAD7[v1] + __PAIR32__(samus_periodic_damage, samus_periodic_subdamage)) >> 16; samus_periodic_subdamage += g_word_94AAD7[v1]; samus_periodic_damage = g_word_94AAF7[v1] + v2; samus_invincibility_timer = 60; samus_knockback_timer = 10; } } } return 0; } static const uint16 g_word_94AB50[16] = { // 0x94AB17 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static const uint16 g_word_94AB70[16] = { 60, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; uint8 BlockReact_AA64_SpikeBlock(void) { int16 v0; int16 v2; if (!samus_invincibility_timer) { v0 = *(uint16 *)&BTS[cur_block_index]; if (v0 >= 0) { int v1 = v0; if (g_word_94AB70[v1] | g_word_94AB50[v1]) { v2 = (g_word_94AB50[v1] + __PAIR32__(samus_periodic_damage, samus_periodic_subdamage)) >> 16; samus_periodic_subdamage += g_word_94AB50[v1]; samus_periodic_damage = g_word_94AB70[v1] + v2; samus_invincibility_timer = 60; samus_knockback_timer = 10; } } } return 1; } static Func_U8 *const kBlockReactLut_AB90[16] = { // 0x94ABB0 ClearCarry_10, SetCarry_3, BlockReact_AA64_SpikeAir, ClearCarry_10, ClearCarry_10, BlockReact_HorizExt, ClearCarry_10, ClearCarry_10, SetCarry_3, SetCarry_3, BlockReact_AA64_SpikeBlock, SetCarry_3, SetCarry_3, BlockReact_VertExt, SetCarry_3, SetCarry_3, }; uint8 BlockFunc_ABB0(void) { uint8 rv; uint16 v0 = grapple_beam_grapple_start_block_x; uint16 RegWord = Mult8x8(grapple_beam_grapple_start_block_y, room_width_in_blocks); cur_block_index = RegWord + v0; do { rv = kBlockReactLut_AB90[(level_data[cur_block_index] & 0xF000) >> 12](); } while (rv & 0x80); return rv; } uint8 BlockFunc_ABE6(void) { // 0x94ABE6 uint8 v0; g_word_7E0D98 = 6; grapple_beam_tmpD84 = grapple_beam_length + 8; while (1) { BlockFunc_A957(); v0 = BlockFunc_ABB0() & 1; if (v0) break; grapple_beam_tmpD84 += 8; if (!--g_word_7E0D98) return 0; } return v0; } void BlockFunc_AC11(void) { // 0x94AC11 grapple_beam_tmpD82 = 2 * grapple_beam_end_angle; grapple_beam_tmpD84 = grapple_beam_length; BlockFunc_A957(); x_pos_of_start_of_grapple_beam = grapple_beam_grapple_start_x; y_pos_of_start_of_grapple_beam = grapple_beam_grapple_start_y; } uint8 BlockFunc_AC31(void) { // 0x94AC31 if (!grapple_beam_length_delta) return 0; if ((grapple_beam_length_delta & 0x8000u) != 0) { uint16 v0 = grapple_beam_length_delta + grapple_beam_length; if ((uint16)(grapple_beam_length_delta + grapple_beam_length) < 8u) { grapple_beam_length_delta = 0; v0 = 8; } grapple_beam_varD8C = v0; grapple_beam_varD8E = 8; grapple_beam_tmpD82 = 2 * grapple_beam_end_angle; uint16 v1 = grapple_beam_length; if (grapple_beam_length == grapple_beam_varD8C) { LABEL_8: grapple_beam_length = grapple_beam_varD8C; return 0; } while (1) { grapple_beam_tmpD8A = v1; grapple_beam_tmpD84 = grapple_beam_varD8E + v1 - 1; BlockFunc_A957(); if (BlockReact_AA64() & 1) goto LABEL_9; v1 = --grapple_beam_tmpD8A; if (grapple_beam_tmpD8A == grapple_beam_varD8C) goto LABEL_8; } } uint16 v3; v3 = grapple_beam_length_delta + grapple_beam_length; if ((uint16)(grapple_beam_length_delta + grapple_beam_length) >= 0x3Fu) { grapple_beam_length_delta = 0; v3 = 63; } grapple_beam_varD8C = v3; grapple_beam_varD8E = 56; grapple_beam_tmpD82 = 2 * grapple_beam_end_angle; uint16 v4; v4 = grapple_beam_length; if (grapple_beam_length != grapple_beam_varD8C) { while (1) { grapple_beam_tmpD8A = v4; grapple_beam_tmpD84 = grapple_beam_varD8E + v4 + 1; BlockFunc_A957(); if (BlockReact_AA64() & 1) break; v4 = ++grapple_beam_tmpD8A; if (grapple_beam_tmpD8A == grapple_beam_varD8C) goto LABEL_15; } LABEL_9: grapple_beam_length = grapple_beam_tmpD8A; return 1; } LABEL_15: grapple_beam_length = grapple_beam_varD8C; return 0; } uint8 HandleMovementAndCollForSamusGrapple(void) { // 0x94ACFE int16 v4; int16 v7; uint16 v3, v6; uint16 v0 = 256; if ((grapple_beam_flags & 1) != 0) v0 = 160; uint16 v1 = grapple_beam_unkD2E + grapple_beam_unkD26; if ((int16)(grapple_beam_unkD2E + grapple_beam_unkD26) >= 0) { Multiply16x16(v1, v0); if (!*(uint16 *)((char *)&mult_product_lo + 1)) return 0; g_word_7E0D9C = *(uint16 *)((char *)&mult_product_lo + 1); grapple_beam_y_quarter_vel = 2 * ((uint16)(*(uint16 *)&grapple_beam_end_subangle + *(uint16 *)((char *)&mult_product_lo + 1)) >> 8); grapple_beam_tmpD84 = grapple_beam_length; uint16 v2; v2 = 2 * grapple_beam_end_angle; if (v2 != grapple_beam_y_quarter_vel) { while (1) { grapple_beam_y_quarter_subvel = v2; grapple_beam_tmpD82 = (v2 + 2) & 0x1FF; if (BlockFunc_ABE6() & 1) break; v2 = (grapple_beam_y_quarter_subvel + 2) & 0x1FF; if (v2 == grapple_beam_y_quarter_vel) goto LABEL_12; } LOBYTE(v4) = 0; HIBYTE(v4) = grapple_beam_y_quarter_subvel >> 1; *(uint16 *)&grapple_beam_end_subangle = v4 | 0x80; grapple_beam_end_angles_mirror = v4 | 0x80; if (g_word_7E0D98 != 6 && g_word_7E0D98 != 5 || grapple_beam_length != 8) goto LABEL_39; LABEL_23: grapple_beam_unkD36 |= 0x8000u; grapple_beam_unkD26 = 0; grapple_beam_unkD2E = 0; return 1; } LABEL_12: *(uint16 *)&grapple_beam_end_subangle += g_word_7E0D9C; grapple_beam_end_angles_mirror = *(uint16 *)&grapple_beam_end_subangle; grapple_beam_unkD36 &= ~0x8000u; if ((--grapple_beam_unkD30 & 0x8000u) != 0) grapple_beam_unkD30 = 0; if ((grapple_beam_unkD2E & 0x8000u) == 0) { v3 = grapple_beam_unkD2E - 6; if ((int16)(grapple_beam_unkD2E - 6) >= 0) { LABEL_19: grapple_beam_unkD2E = v3; return 0; } } else { v3 = grapple_beam_unkD2E + 6; if ((int16)(grapple_beam_unkD2E + 6) < 0) goto LABEL_19; } v3 = 0; goto LABEL_19; } Multiply16x16(-v1, v0); if (!*(uint16 *)((char *)&mult_product_lo + 1)) return 0; g_word_7E0D9C = -*(uint16 *)((char *)&mult_product_lo + 1); grapple_beam_y_quarter_vel = 2 * ((uint16)(*(uint16 *)&grapple_beam_end_subangle - *(uint16 *)((char *)&mult_product_lo + 1)) >> 8); grapple_beam_tmpD84 = grapple_beam_length; uint16 v5; v5 = 2 * grapple_beam_end_angle; if (v5 == grapple_beam_y_quarter_vel) { LABEL_28: *(uint16 *)&grapple_beam_end_subangle += g_word_7E0D9C; grapple_beam_end_angles_mirror = *(uint16 *)&grapple_beam_end_subangle; grapple_beam_unkD36 &= ~0x8000u; if ((--grapple_beam_unkD30 & 0x8000u) != 0) grapple_beam_unkD30 = 0; if ((grapple_beam_unkD2E & 0x8000u) == 0) { v6 = grapple_beam_unkD2E - 6; if ((int16)(grapple_beam_unkD2E - 6) >= 0) { LABEL_35: grapple_beam_unkD2E = v6; return 0; } } else { v6 = grapple_beam_unkD2E + 6; if ((int16)(grapple_beam_unkD2E + 6) < 0) goto LABEL_35; } v6 = 0; goto LABEL_35; } while (1) { grapple_beam_y_quarter_subvel = v5; grapple_beam_tmpD82 = (v5 - 2) & 0x1FF; if (BlockFunc_ABE6() & 1) break; v5 = (grapple_beam_y_quarter_subvel - 2) & 0x1FF; if (v5 == grapple_beam_y_quarter_vel) goto LABEL_28; } LOBYTE(v7) = 0; HIBYTE(v7) = grapple_beam_y_quarter_subvel >> 1; *(uint16 *)&grapple_beam_end_subangle = v7 | 0x80; grapple_beam_end_angles_mirror = v7 | 0x80; if ((g_word_7E0D98 == 6 || g_word_7E0D98 == 5) && grapple_beam_length == 8) goto LABEL_23; LABEL_39: grapple_beam_unkD30 = 16; grapple_beam_unkD26 = -((int16)grapple_beam_unkD26 >> 1); grapple_beam_unkD2E = -((int16)grapple_beam_unkD2E >> 1); return 1; } uint8 BlockFunc_AEE3(void) { // 0x94AEE3 if (((grapple_beam_unkD26 ^ *(uint16 *)&grapple_beam_end_subangle) & 0x8000u) != 0) { grapple_beam_unkD38 = 0; return 1; } else { if (++grapple_beam_unkD38 == 32) grapple_beam_function = FUNC16(GrappleBeam_Func2); grapple_beam_unkD26 = 0; grapple_beam_unkD2E = 0; return 1; } } uint8 ClearCarry_11(void) { // 0x94AF0B return 0; } void GrappleFunc_AF87(void) { // 0x94AF87 for (int i = 30; i >= 0; i -= 8) { int v1 = i >> 1; grapple_segment_anim_instr_ptrs[v1] = addr_word_94B197; grapple_segment_anim_instr_timers[v1 + 15] = addr_word_94B193; grapple_segment_anim_instr_timers[v1 + 14] = addr_word_94B18F; grapple_segment_anim_instr_timers[v1 + 13] = addr_word_94B18B; grapple_segment_anim_instr_timers[v1] = 1; *(uint16 *)((char *)&grapple_point_anim_ptr + i) = 1; *(uint16 *)((char *)&grapple_point_anim_timer + i) = 1; *(uint16 *)((char *)&grapple_beam_unkD3C + i) = 1; } } uint16 CallGrappleInstr(uint32 ea, uint16 j) { switch (ea) { case fnGrappleInstr_Goto: return GrappleInstr_Goto(j); // 0x94b0f4 default: return Unreachable(); } } void HandleGrappleBeamGfx(void) { // 0x94AFBA int16 RegWord; // dx R18_ = grapple_beam_end_x_pos - x_pos_of_start_of_grapple_beam_prevframe; R20_ = grapple_beam_end_y_pos - y_pos_of_start_of_grapple_beam_prevframe; uint16 v0 = 2 * CalculateAngleFromXY(); R26_ = 0; R28_ = 0; int v1 = v0 >> 1; uint16 v2 = 8 * kSinCosTable8bit_Sext[v1 + 64]; if ((kSinCosTable8bit_Sext[v1 + 64] & 0x1000) != 0) --R28_; *(uint16 *)((char *)&R26_ + 1) = v2; g_word_7E001E = 0; R32 = 0; uint16 v3 = 8 * kSinCosTable8bit_Sext[v1]; if ((kSinCosTable8bit_Sext[v1] & 0x1000) != 0) --R32; *(uint16 *)((char *)&g_word_7E001E + 1) = v3; R38 = (uint16)(*(uint16 *)&grapple_beam_end_subangle & 0x8000) >> 1; R38 |= 2 * ((*(uint16 *)&grapple_beam_end_subangle ^ R38) & 0x4000 ^ 0x4000); R20_ = x_pos_of_start_of_grapple_beam_prevframe - layer1_x_pos - 4; R18_ = 0; R24_ = y_pos_of_start_of_grapple_beam_prevframe - layer1_y_pos - 4; R22_ = 0; if ((grapple_beam_length & 0x8000u) == 0) { RegWord = grapple_beam_length / 8; if (RegWord >= 0) { R40 = (RegWord & 0xF) - 1; uint16 v5 = 30; do { int i, v6 = v5 >> 1; uint16 v10; if (grapple_segment_anim_instr_timers[v6]-- == 1) { for (i = grapple_segment_anim_instr_ptrs[v6]; ; ) { uint16 *v9 = (uint16 *)RomPtr_94(i); v10 = *v9; if ((*v9 & 0x8000u) == 0) break; R36 = *v9; i = CallGrappleInstr(v10 | 0x940000, i + 2); } int v11 = v5 >> 1; grapple_segment_anim_instr_timers[v11] = v10; grapple_segment_anim_instr_ptrs[v11] = i + 4; } if (((R24_ | R20_) & 0xFF00) != 0) break; uint16 v12 = *(uint16 *)RomPtr_94(grapple_segment_anim_instr_ptrs[v5 >> 1] - 2); DrawGrappleOams(v12); v5 -= 2; --R40; } while ((R40 & 0x8000u) == 0); if (samus_pose == kPose_B2_FaceR_Grapple_Air || samus_pose == kPose_B3_FaceL_Grapple_Air) DrawGrappleOams3(); else DrawGrappleOams2(); } } } void DrawGrappleOams(uint16 j) { // 0x94B0AA OamEnt *v2; unsigned int v3; // kr00_4 unsigned int v4; // kr04_4 uint16 v1 = oam_next_ptr; v2 = gOamEnt(oam_next_ptr); *(uint16 *)&v2->xcoord = R20_; v3 = __PAIR32__(R28_, R26_) + __PAIR32__(R20_, R18_); R20_ = HIWORD(v3); R18_ = v3; *(uint16 *)&v2->ycoord = R24_; v4 = __PAIR32__(R32, g_word_7E001E) + __PAIR32__(R24_, R22_); R24_ = HIWORD(v4); R22_ = v4; *(uint16 *)&v2->charnum = R38 | j; oam_next_ptr = v1 + 4; } uint16 GrappleInstr_Goto(uint16 j) { // 0x94B0F4 return *(uint16 *)RomPtr_94(j); } void DrawGrappleOams2(void) { // 0x94B0F9 int16 v1; OamEnt *v2; int16 v4; if (((grapple_beam_end_y_pos - layer1_y_pos) & 0xFF00) == 0) { uint16 v0 = oam_next_ptr; v1 = grapple_beam_end_x_pos - layer1_x_pos - 4; v2 = gOamEnt(oam_next_ptr); *(uint16 *)&v2->xcoord = v1; if ((v1 & 0x100) != 0) { int v3 = v0 >> 1; R34 = kOamExtra_Address_And_X8Large[v3]; v4 = kOamExtra_X8Small_And_Large[v3] | *(uint16 *)RomPtr_RAM(R34); *(uint16 *)RomPtr_RAM(R34) = v4; } *(uint16 *)&v2->ycoord = grapple_beam_end_y_pos - layer1_y_pos - 4; *(uint16 *)&v2->charnum = 14880; oam_next_ptr = v0 + 4; } } void DrawGrappleOams3(void) { // 0x94B14B int16 v1; OamEnt *v2; int16 v4; uint16 v0 = oam_next_ptr; v1 = grapple_beam_end_x_pos - layer1_x_pos - 4; v2 = gOamEnt(oam_next_ptr); *(uint16 *)&v2->xcoord = v1; if ((v1 & 0x100) != 0) { int v3 = v0 >> 1; R34 = kOamExtra_Address_And_X8Large[v3]; v4 = kOamExtra_X8Small_And_Large[v3] | *(uint16 *)RomPtr_RAM(R34); *(uint16 *)RomPtr_RAM(R34) = v4; } *(uint16 *)&v2->ycoord = grapple_beam_end_y_pos - layer1_y_pos - 4; *(uint16 *)&v2->charnum = 14880; oam_next_ptr = v0 + 4; }