Files
sm-vita/src/sm_94.c
2023-03-07 00:23:44 +01:00

3064 lines
85 KiB
C

// 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;
}