sa1: more player alignment, match Player_AirInputControls

This commit is contained in:
Oliver Bell committed 2026-04-19 11:32:49 +01:00
1 parent 02d6a79a87
commit c7f2635e4c
10 files changed
+444 -362

No files matched your search

@@ -1,119 +0,0 @@
.include "constants/constants.inc"
.syntax unified
.text
push {r4, r5, r6, r7, lr}
adds r4, r0, #0 @ r4 = p
ldr r0, [r4, #0x30]
lsls r6, r0, #1 @ r6 = qPlayerAccel
ldr r7, [r4, #0x2c] @ r7 = qPlayerMaxSpeed
adds r0, r4, #0
adds r0, #0x40
movs r5, #0
ldrsb r5, [r0, r5]
cmp r5, #0xf @ if (p->charState == CHARSTATE_HIT_AIR)
beq _0804466A_return
ldr r1, [r4, #0x10]
movs r0, #0x10
mov ip, r0
adds r0, r1, #0
mov r2, ip
ands r0, r2
cmp r0, #0 @ if (p->moveState & MOVESTATE_FLIP_WITH_MOVE_DIR)
bne _08044634
ldrh r2, [r4, #8] @ r2 = p->qSpeedAirX
ldrh r3, [r4, #0x38]
movs r0, #0x20
ands r0, r3
cmp r0, #0
beq _080445FE
cmp r5, #0x17
beq _080445DC
movs r0, #1
orrs r1, r0
str r1, [r4, #0x10]
_080445DC:
lsls r0, r2, #0x10
asrs r0, r0, #0x10
subs r0, r0, r6
lsls r0, r0, #0x10
lsrs r2, r0, #0x10
asrs r0, r0, #0x10
rsbs r1, r7, #0
cmp r0, r1
bge _08044632
adds r0, r0, r6
lsls r0, r0, #0x10
lsrs r2, r0, #0x10
asrs r0, r0, #0x10
cmp r0, r1
ble _08044632
lsls r0, r1, #0x10
b _08044630
_080445FE:
mov r0, ip
ands r0, r3
cmp r0, #0
beq _08044632
cmp r5, #0x17
beq _08044612
movs r0, #2
rsbs r0, r0, #0
ands r1, r0
str r1, [r4, #0x10]
_08044612:
lsls r0, r2, #0x10
asrs r0, r0, #0x10
adds r0, r0, r6
lsls r0, r0, #0x10
lsrs r2, r0, #0x10
asrs r0, r0, #0x10
cmp r0, r7
ble _08044632
subs r0, r0, r6
lsls r0, r0, #0x10
lsrs r2, r0, #0x10
asrs r0, r0, #0x10
cmp r0, r7
bge _08044632
lsls r0, r7, #0x10
_08044630:
lsrs r2, r0, #0x10
_08044632:
strh r2, [r4, #8]
_08044634:
ldrh r1, [r4, #0xa]
ldr r0, _08044654 @ =0x0000BCFF
cmp r1, r0
bls _0804466A_return
ldrh r1, [r4, #8]
lsls r0, r1, #0x10
asrs r1, r0, #0x10
asrs r0, r0, #0x15
cmp r0, #0
bge _08044658
subs r0, r1, r0
lsls r0, r0, #0x10
lsrs r1, r0, #0x10
cmp r0, #0
ble _08044668
b _08044666
.align 2, 0
_08044654: .4byte 0x0000BCFF
_08044658:
cmp r0, #0
ble _0804466A_return
subs r0, r1, r0
lsls r0, r0, #0x10
lsrs r1, r0, #0x10
cmp r0, #0
bge _08044668
_08044666:
movs r1, #0
_08044668:
strh r1, [r4, #8]
_0804466A_return:
pop {r4, r5, r6, r7}
pop {r0}
bx r0
.syntax divided
+240 -111
View File
@@ -3427,55 +3427,109 @@ void SA2_LABEL(sub_8023260)(Player *p)
}
#endif
// ALIGNED UP TO HERE
void SA2_LABEL(sub_80232D0)(Player *p)
{
Camera *cam = &gCamera;
s32 qWorldX = p->qWorldX;
s32 qWorldY = p->qWorldY;
s32 unkX, unkY;
#ifndef COLLECT_RINGS_ROM
if (p->playerID == PLAYER_1) {
s32 unkX = SA2_LABEL(gUnknown_080D650C)[gCurrentLevel][0];
s32 unkY;
#if (GAME == GAME_SA2)
if (IS_BOSS_STAGE(gCurrentLevel)) {
if (gCurrentLevel & 0x2) {
unkX = SA2_LABEL(gUnknown_080D650C)[gCurrentLevel][0];
if ((unkX >= 0) && (qWorldX >= Q(unkX))) {
s32 ix = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][0];
s32 iy = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][1];
if ((unkX >= 0) && (qWorldX >= Q(unkX)) && (cam->SA2_LABEL(unk8) != 0) && !(cam->SA2_LABEL(unk50) & 0x1)) {
s32 r3 = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][0];
s32 r2 = Q(r3);
qWorldX += r2;
qWorldX += Q(ix);
qWorldY += Q(iy);
if (gNumSingleplayerCharacters == NUM_SINGLEPLAYER_CHARS_MAX) {
gPartner.qWorldX += r2;
if (gCheese != NULL) {
gCheese->posX += Q(ix);
gCheese->posY += Q(iy);
}
gWorldSpeedX = Q(ix);
gWorldSpeedY = Q(iy);
sub_8039F14(Q(ix), Q(iy));
gBossRingsShallRespawn = TRUE;
cam->x += ix;
cam->SA2_LABEL(unk20) += ix;
cam->SA2_LABEL(unk10) += ix;
cam->y += iy;
cam->SA2_LABEL(unk24) += iy;
cam->unk14 += iy;
}
}
} else if ((gPlayer.moveState & MOVESTATE_GOAL_REACHED) && (gSpecialRingCount >= SPECIAL_STAGE_REQUIRED_SP_RING_COUNT))
#endif
{
unkX = SA2_LABEL(gUnknown_080D650C)[gCurrentLevel][0];
if ((unkX >= 0) && (qWorldX >= Q(unkX)) && (cam->SA2_LABEL(unk8) != 0) && !(cam->SA2_LABEL(unk50) & 0x1)) {
s32 ix = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][0];
qWorldX += Q(ix);
#if (GAME == GAME_SA1)
if (gNumSingleplayerCharacters == NUM_SINGLEPLAYER_CHARS_MAX) {
gPartner.qWorldX += Q(ix);
}
#endif
cam->x += ix;
cam->SA2_LABEL(unk20) += ix;
#if (GAME == GAME_SA2)
cam->SA2_LABEL(unk10) += ix;
if (gCheese != NULL) {
gCheese->posX += Q(ix);
}
#endif
}
cam->x += r3;
cam->SA2_LABEL(unk20) += r3;
}
// _08043F3E
unkY = SA2_LABEL(gUnknown_080D650C)[gCurrentLevel][1];
if ((unkY >= 0) && (qWorldY >= Q(unkY)) && (cam->SA2_LABEL(unkC) != 0) && !(cam->SA2_LABEL(unk50) & 0x2)) {
s32 iy = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][1];
s32 worldY = iy * CAM_REGION_WIDTH;
qWorldY += Q(worldY);
unkY = SA2_LABEL(gUnknown_080D650C)[gCurrentLevel][1];
#if (GAME == GAME_SA1)
if (gNumSingleplayerCharacters == NUM_SINGLEPLAYER_CHARS_MAX) {
gPartner.qWorldY += Q(worldY);
}
#endif
if ((unkY >= 0) && (qWorldY >= Q(unkY)) && (cam->SA2_LABEL(unkC) != 0) && !(cam->SA2_LABEL(unk50) & 0x2)) {
s32 r3 = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][1] << 8;
qWorldY += Q(r3);
if (gNumSingleplayerCharacters == NUM_SINGLEPLAYER_CHARS_MAX) {
gPartner.qWorldY += Q(r3);
#if (GAME == GAME_SA1)
// TODO: look at the data and determine if using `worldY` in sa1 was a bug
cam->y += worldY;
cam->SA2_LABEL(unk24) += worldY;
#elif (GAME == GAME_SA2)
cam->y += Q(iy);
cam->SA2_LABEL(unk24) += Q(iy);
if (gCheese != NULL) {
gCheese->posY += Q(worldY);
}
#endif
}
cam->y += r3;
cam->SA2_LABEL(unk24) += r3;
}
}
// _08043F9C
#endif
if ((p->moveState & (MOVESTATE_80000000 | MOVESTATE_DEAD)) != MOVESTATE_DEAD) {
// _08043F9C + 0xC
#if (GAME == GAME_SA2)
s32 camMinY, camMaxY;
#endif
s32 qNoclipWorldX, qNoclipWorldY;
Camera *cam2 = &gCamera;
s32 qPlayerY = p->qWorldY;
if (!(p->moveState & MOVESTATE_80000000)) {
bool32 outOfBounds;
// These blocks are basically the same but the gravity check was swapped in SA2
// TODO: match without gotos
#if (GAME == GAME_SA1)
if (!(gStageFlags & STAGE_FLAG__GRAVITY_INVERTED)) {
if (qPlayerY >= Q(cam2->maxY) - 1) {
outOfBounds = TRUE;
@@ -3490,33 +3544,83 @@ void SA2_LABEL(sub_80232D0)(Player *p)
outOfBounds = FALSE;
lab:
#elif (GAME == GAME_SA2)
#ifndef COLLECT_RINGS_ROM
if (GRAVITY_IS_INVERTED) {
if (qPlayerY > Q(gCamera.minY)) {
goto lbl0;
} else {
outOfBounds = TRUE;
}
} else {
s32 qMaxY = Q(cam2->maxY) - 1;
outOfBounds = 1;
if (qPlayerY < qMaxY) {
lbl0:
outOfBounds = FALSE;
}
}
#else
{
s32 qMaxY = Q(cam2->maxY) - 1;
outOfBounds = FALSE;
if (qPlayerY >= qMaxY) {
lbl0:
outOfBounds = TRUE;
}
}
#endif
#endif
if (outOfBounds) {
// _08044004
s32 qSpeedY;
p->moveState |= MOVESTATE_DEAD;
#ifndef COLLECT_RINGS_ROM
if (p->moveState & MOVESTATE_IN_WATER) {
p->qSpeedAirY = -Q(PLAYER_JUMP_HEIGHT_UNDER_WATER);
} else {
} else
#endif
{
p->qSpeedAirY = -Q(PLAYER_JUMP_HEIGHT);
}
// _0804401E + 0x2
#if (GAME == GAME_SA1)
if (!(gStageFlags & STAGE_FLAG__GRAVITY_INVERTED)) {
qWorldY = Q(cam->maxY) - 1;
} else {
qWorldY = Q(cam->minY);
}
#elif (GAME == GAME_SA2)
#ifndef COLLECT_RINGS_ROM
qWorldY = GRAVITY_IS_INVERTED ? Q(cam->minY) : Q(cam->maxY) - 1;
#else
qWorldY = Q(cam->maxY) - 1;
#endif
#endif
}
}
// _08044042
#if (GAME == GAME_SA2)
if (IS_BOSS_STAGE(gCurrentLevel)) {
camMinY = gBossCameraClampYLower;
camMaxY = gBossCameraClampYUpper;
} else {
camMinY = cam->minY;
camMaxY = cam->maxY;
}
#endif
qNoclipWorldX = qWorldX;
qNoclipWorldY = qWorldY;
qWorldX = CLAMP(qWorldX, Q(cam->minX), Q(cam->maxX) - 1);
#if (GAME == GAME_SA1)
qWorldY = CLAMP(qWorldY, Q(cam->minY), Q(cam->maxY) - 1);
#elif (GAME == GAME_SA2)
qWorldY = CLAMP(qWorldY, Q(camMinY), Q(camMaxY) - 1);
#endif
if (qWorldX != qNoclipWorldX) {
p->qSpeedAirX = Q(0);
p->qSpeedGround = Q(0);
@@ -3527,6 +3631,25 @@ void SA2_LABEL(sub_80232D0)(Player *p)
p->qSpeedGround = Q(0);
}
#if (GAME == GAME_SA2)
#ifndef COLLECT_RINGS_ROM
if (IS_BOSS_STAGE(gCurrentLevel)) {
s32 qPXMin = (Q(cam->SA2_LABEL(unk10)));
if (qWorldX < qPXMin + Q(8.0)) {
qWorldX = qPXMin + Q(8.0);
p->qSpeedGround = BOSS_VELOCITY_X;
p->qSpeedAirX = BOSS_VELOCITY_X;
p->moveState &= ~MOVESTATE_FACING_LEFT;
} else if (qWorldX > (qPXMin + Q(312.0))) {
qWorldX = (qPXMin + Q(312.0));
p->qSpeedGround = BOSS_VELOCITY_X;
p->qSpeedAirX = BOSS_VELOCITY_X;
}
}
#endif
#endif
p->qWorldX = qWorldX;
p->qWorldY = qWorldY;
}
@@ -3791,8 +3914,8 @@ NONMATCH("asm/non_matching/game/sa1/stage/Player__sub_8044434.inc", bool32 sub_8
END_NONMATCH
#endif // (GAME == GAME_SA1)
// (91.12%) https://decomp.me/scratch/hJuDa
NONMATCH("asm/non_matching/game/sa1/stage/Player__Player_AirInputControls.inc", void Player_AirInputControls(Player *p))
// ALIGNED UP TO HERE
void Player_AirInputControls(Player *p)
{
s32 r5 = p->acceleration * 2;
s32 r6 = p->maxSpeed;
@@ -3803,6 +3926,9 @@ NONMATCH("asm/non_matching/game/sa1/stage/Player__Player_AirInputControls.inc",
u16 qAirSpeedU = p->qSpeedAirX;
if (p->heldInput & DPAD_LEFT) {
#if (GAME == GAME_SA1) && !defined(NON_MATCHING)
qAirSpeedS = qAirSpeedU;
#endif
if (p->charState != CHARSTATE_BOUNCE) {
p->moveState |= MOVESTATE_FACING_LEFT;
}
@@ -3837,10 +3963,13 @@ NONMATCH("asm/non_matching/game/sa1/stage/Player__Player_AirInputControls.inc",
}
}
}
#if (GAME == GAME_SA1) && !defined(NON_MATCHING)
p->qSpeedAirX = (r5 = qAirSpeedU);
#else
p->qSpeedAirX = qAirSpeedU;
#endif
}
#if (GAME == GAME_SA1)
if ((u16)p->qSpeedAirY > (u16)(-Q(67) - 1)) {
s16 qSpeedAirX = p->qSpeedAirX;
s16 qSpeedAirXFrac = p->qSpeedAirX >> 5;
@@ -3861,8 +3990,8 @@ NONMATCH("asm/non_matching/game/sa1/stage/Player__Player_AirInputControls.inc",
}
}
}
#endif
}
END_NONMATCH
#if (GAME == GAME_SA1)
void Player_8044670(Player *p)
@@ -4705,15 +4834,15 @@ static inline bool32 DeadPlayerLeftScreen(Player *p, struct Camera *cam, s32 pla
}
}
#elif (GAME == GAME_SA2)
if (GRAVITY_IS_INVERTED) {
if (playerY <= Q(cam->y - 80)) {
return TRUE;
if (GRAVITY_IS_INVERTED) {
if (playerY <= Q(cam->y - 80)) {
return TRUE;
}
} else {
if (playerY >= Q(cam->y) + Q(DISPLAY_HEIGHT + 80) - 1) {
return TRUE;
}
}
} else {
if (playerY >= Q(cam->y) + Q(DISPLAY_HEIGHT + 80) - 1) {
return TRUE;
}
}
#endif
return FALSE;
}
@@ -4742,8 +4871,8 @@ void Task_PlayerDied(void)
PLAYERFN_UPDATE_POSITION(p);
PLAYERFN_UPDATE_AIR_FALL_SPEED(p);
#elif (GAME == GAME_SA2)
PLAYERFN_UPDATE_AIR_FALL_SPEED(p);
PLAYERFN_UPDATE_POSITION(p);
PLAYERFN_UPDATE_AIR_FALL_SPEED(p);
PLAYERFN_UPDATE_POSITION(p);
#endif
SA2_LABEL(sub_802486C)(p, psi1);
SA2_LABEL(sub_8024B10)(p, psi1);
@@ -4833,23 +4962,23 @@ void Task_PlayerMain(void)
m4aSongNumStop(27);
m4aSongNumStop(SE_TAILS_PROPELLER_FLYING);
#elif (GAME == GAME_SA2)
// TODO: macro IS_SONG_PLAYING(...)
if (gMPlayTable[0].info->songHeader == gSongTable[MUS_DROWNING].header) {
m4aSongNumStartOrContinue(gLevelSongs[gCurrentLevel]);
}
if (gMPlayTable[0].info->songHeader == gSongTable[MUS_INVINCIBILITY].header) {
m4aSongNumStartOrContinue(gLevelSongs[gCurrentLevel]);
}
// TODO: macro IS_SONG_PLAYING(...)
if (gMPlayTable[0].info->songHeader == gSongTable[MUS_DROWNING].header) {
m4aSongNumStartOrContinue(gLevelSongs[gCurrentLevel]);
}
if (gMPlayTable[0].info->songHeader == gSongTable[MUS_INVINCIBILITY].header) {
m4aSongNumStartOrContinue(gLevelSongs[gCurrentLevel]);
}
m4aSongNumStop(MUS_DROWNING);
m4aSongNumStop(MUS_DROWNING);
if (p->character == CHARACTER_TAILS) {
m4aSongNumStop(SE_TAILS_PROPELLER_FLYING);
}
if (p->character == CHARACTER_TAILS) {
m4aSongNumStop(SE_TAILS_PROPELLER_FLYING);
}
if (p->character == CHARACTER_CREAM) {
m4aSongNumStop(SE_CREAM_FLYING);
}
if (p->character == CHARACTER_CREAM) {
m4aSongNumStop(SE_CREAM_FLYING);
}
#endif
if (p->secondsUntilDrown < 0) {
@@ -5554,10 +5683,10 @@ NONMATCH("asm/non_matching/game/sa1/stage/Player__sa2__sub_8024B10.inc", void SA
r2;
});
#else
bool32 cond = ({
bool32 r2 = s->prevVariant == 0xFF || s->prevAnim == 0xFFFF;
r2;
});
bool32 cond = ({
bool32 r2 = s->prevVariant == 0xFF || s->prevAnim == 0xFFFF;
r2;
});
#endif
top:
@@ -5569,8 +5698,8 @@ top:
#if (GAME == GAME_SA1)
if (p->charState == CHARSTATE_WALK_A || p->charState == 23 || p->charState == 32 || p->charState == 40)
#elif (GAME == GAME_SA2)
if (p->charState == CHARSTATE_WALK_A || p->charState == CHARSTATE_GRINDING || p->charState == CHARSTATE_ICE_SLIDE
|| p->charState == CHARSTATE_WALK_B || (p->charState == CHARSTATE_CREAM_CHAO_ATTACK && p->character == CHARACTER_CREAM))
if (p->charState == CHARSTATE_WALK_A || p->charState == CHARSTATE_GRINDING || p->charState == CHARSTATE_ICE_SLIDE
|| p->charState == CHARSTATE_WALK_B || (p->charState == CHARSTATE_CREAM_CHAO_ATTACK && p->character == CHARACTER_CREAM))
#endif
{
if (p->charState != 32) {
@@ -5869,7 +5998,7 @@ top:
#if (GAME == GAME_SA1)
send->unk0 = 0x1000;
#elif (GAME == GAME_SA2)
send->unk0 = 0x5000;
send->unk0 = 0x5000;
#endif
send->x = I(p->qWorldX) + p->SA2_LABEL(unk7C);
send->y = I(p->qWorldY);
@@ -6095,20 +6224,20 @@ void Player_TransitionCancelFlyingAndBoost(Player *p)
p->moveState &= ~MOVESTATE_8000;
#elif (GAME == GAME_SA2)
if (p->moveState & MOVESTATE_20000) {
m4aSongNumStop(SE_281);
}
if (p->moveState & MOVESTATE_20000) {
m4aSongNumStop(SE_281);
}
p->moveState &= ~(MOVESTATE_SOME_ATTACK | MOVESTATE_10000000 | MOVESTATE_1000000 | MOVESTATE_80000 | MOVESTATE_40000 | MOVESTATE_20000
| MOVESTATE_8000 | MOVESTATE_4000 | MOVESTATE_2000 | MOVESTATE_SPINDASH | MOVESTATE_200 | MOVESTATE_100 | MOVESTATE_20
| MOVESTATE_FLIP_WITH_MOVE_DIR);
p->moveState &= ~(MOVESTATE_SOME_ATTACK | MOVESTATE_10000000 | MOVESTATE_1000000 | MOVESTATE_80000 | MOVESTATE_40000
| MOVESTATE_20000 | MOVESTATE_8000 | MOVESTATE_4000 | MOVESTATE_2000 | MOVESTATE_SPINDASH | MOVESTATE_200
| MOVESTATE_100 | MOVESTATE_20 | MOVESTATE_FLIP_WITH_MOVE_DIR);
p->SA2_LABEL(unk61) = 0;
p->SA2_LABEL(unk62) = 0;
p->SA2_LABEL(unk63) = 0;
p->SA2_LABEL(unk61) = 0;
p->SA2_LABEL(unk62) = 0;
p->SA2_LABEL(unk63) = 0;
p->SA2_LABEL(unk71) = 0;
p->SA2_LABEL(unk70) = FALSE;
p->SA2_LABEL(unk71) = 0;
p->SA2_LABEL(unk70) = FALSE;
#endif
if (p->character == CHARACTER_TAILS) {
@@ -6120,13 +6249,13 @@ void Player_TransitionCancelFlyingAndBoost(Player *p)
p->moveState &= ~(MOVESTATE_4000000 | MOVESTATE_2000000);
}
#elif (GAME == GAME_SA2)
if (p->character == CHARACTER_CREAM) {
m4aSongNumStop(SE_CREAM_FLYING);
}
if (p->character == CHARACTER_CREAM) {
m4aSongNumStop(SE_CREAM_FLYING);
}
if (p->character == CHARACTER_SONIC) {
p->moveState &= ~MOVESTATE_BOOST_EFFECT_ON;
}
if (p->character == CHARACTER_SONIC) {
p->moveState &= ~MOVESTATE_BOOST_EFFECT_ON;
}
#endif
}
@@ -6350,14 +6479,14 @@ void SA2_LABEL(sub_8029CA0)(Player *p)
s32 rot;
if (((p->rotation + Q(0.375)) & 0xFF) < Q(0.75))
#else
s32 rot = p->rotation;
if (((rot + Q(0.375)) & 0xFF) < Q(0.75))
s32 rot = p->rotation;
if (((rot + Q(0.375)) & 0xFF) < Q(0.75))
#endif
{
#if (GAME == GAME_SA1)
rot = GET_ROTATED_ACCEL(p->rotation);
#else
rot = GET_ROTATED_ACCEL(rot);
rot = GET_ROTATED_ACCEL(rot);
#endif
if (p->qSpeedGround != 0) {
@@ -6377,15 +6506,15 @@ void SA2_LABEL(sub_8029CE0)(Player *p)
}
}
#else
void SA2_LABEL(sub_8029CE0)(Player *p)
{
s32 rot = p->rotation;
if (((rot + Q(0.375)) & 0xFF) < Q(0.75)) {
s32 other = GET_ROTATED_ACCEL_2(rot);
void SA2_LABEL(sub_8029CE0)(Player * p)
{
s32 rot = p->rotation;
if (((rot + Q(0.375)) & 0xFF) < Q(0.75)) {
s32 other = GET_ROTATED_ACCEL_2(rot);
p->qSpeedGround += other;
p->qSpeedGround += other;
}
}
}
#endif
void SA2_LABEL(sub_8029D14)(Player *p)
@@ -6393,7 +6522,7 @@ void SA2_LABEL(sub_8029D14)(Player *p)
#ifndef NON_MATCHING
register s32 grndSpeed asm("r2") = p->qSpeedGround;
#else
s32 grndSpeed = p->qSpeedGround;
s32 grndSpeed = p->qSpeedGround;
#endif
if ((((p->rotation + Q(0.375)) & 0xFF) < Q(0.75)) && grndSpeed != 0) {
@@ -6476,13 +6605,13 @@ bool32 SA2_LABEL(sub_8029DE8)(Player *p)
return TRUE;
}
#elif (GAME == GAME_SA2)
if (GRAVITY_IS_INVERTED) {
if (playerY <= Q(cam->minY))
return TRUE;
} else {
if (playerY >= Q(cam->maxY) - 1)
return TRUE;
}
if (GRAVITY_IS_INVERTED) {
if (playerY <= Q(cam->minY))
return TRUE;
} else {
if (playerY >= Q(cam->maxY) - 1)
return TRUE;
}
#endif
}
@@ -6504,13 +6633,13 @@ bool32 DeadPlayerLeftScreen_UnusedCopy(Player *p)
return TRUE;
}
#elif (GAME == GAME_SA2)
if (GRAVITY_IS_INVERTED) {
if (playerY <= Q(cam->y - 80))
return TRUE;
} else {
if (playerY >= Q(cam->y) + Q(DISPLAY_HEIGHT + 80) - 1)
return TRUE;
}
if (GRAVITY_IS_INVERTED) {
if (playerY <= Q(cam->y - 80))
return TRUE;
} else {
if (playerY >= Q(cam->y) + Q(DISPLAY_HEIGHT + 80) - 1)
return TRUE;
}
#endif
}
+3 -3
View File
@@ -108,9 +108,9 @@ void Task_802EE78(void)
gCamera.x += x;
gCamera.y += y;
gCamera.unk20 += x;
gCamera.unk24 += y;
gCamera.unk10 += x;
gCamera.SA2_LABEL(unk20) += x;
gCamera.SA2_LABEL(unk24) += y;
gCamera.SA2_LABEL(unk10) += x;
gCamera.unk14 += y;
if (gCheese != NULL) {
+3 -3
View File
@@ -470,10 +470,10 @@ static void Task_DestructionSceneOutro(void)
gCamera.x += x;
gCamera.y += y;
gCamera.unk20 += x;
gCamera.unk24 += y;
gCamera.SA2_LABEL(unk20) += x;
gCamera.SA2_LABEL(unk24) += y;
gCamera.unk10 += x;
gCamera.SA2_LABEL(unk10) += x;
gCamera.unk14 += y;
cheese = gCheese;
+14 -14
View File
@@ -225,9 +225,9 @@ void CreateBossRunManager(u8 bossIndex)
gCamera.x += x - 120;
gCamera.y += y - 120;
gCamera.unk20 += x - 120;
gCamera.unk24 += y - 120;
gCamera.unk10 += x - 120;
gCamera.SA2_LABEL(unk20) += x - 120;
gCamera.SA2_LABEL(unk24) += y - 120;
gCamera.SA2_LABEL(unk10) += x - 120;
gCamera.unk14 += y - 120;
cheese = gCheese;
@@ -269,13 +269,13 @@ static void Task_BossRunManagerMain(void)
gPlayer.rotation = 0;
if (I(gPlayer.qWorldX) - 120 != gCamera.x) {
if (I(gPlayer.qWorldX) - 120 > gCamera.x) {
gCamera.unk20++;
gCamera.SA2_LABEL(unk20)++;
gCamera.x++;
gCamera.unk10++;
gCamera.SA2_LABEL(unk10)++;
} else {
gCamera.unk20--;
gCamera.SA2_LABEL(unk20)--;
gCamera.x--;
gCamera.unk10--;
gCamera.SA2_LABEL(unk10)--;
}
}
} else if (gPlayer.qWorldX < Q(42700) && gPlayer.qWorldX > Q(gUnknown_080D8808[6][0] + 20)) {
@@ -305,8 +305,8 @@ static void Task_BossRunManagerMain(void)
sub_8039F50(r6, manager->bossIndex);
gBossRingsShallRespawn = 1;
gCamera.x += r4;
gCamera.unk20 += r4;
gCamera.unk10 += r4;
gCamera.SA2_LABEL(unk20) += r4;
gCamera.SA2_LABEL(unk10) += r4;
if (gCheese != NULL) {
gCheese->posX += r6;
}
@@ -315,7 +315,7 @@ static void Task_BossRunManagerMain(void)
}
}
} else if (manager->bossIndex <= 5) {
if (gCamera.unk10 > sBossRunCameraYTriggers[manager->bossIndex]) {
if (gCamera.SA2_LABEL(unk10) > sBossRunCameraYTriggers[manager->bossIndex]) {
gBossRingsShallRespawn = 1;
gBossRingsRespawnCount = 10;
gPlayer.checkpointTime = gCourseTime;
@@ -332,8 +332,8 @@ static void Task_BossRunManagerMain(void)
sub_8039F50(r5, manager->bossIndex);
gBossRingsShallRespawn = 1;
gCamera.x += r4;
gCamera.unk20 += r4;
gCamera.unk10 += r4;
gCamera.SA2_LABEL(unk20) += r4;
gCamera.SA2_LABEL(unk10) += r4;
if (gCheese != NULL) {
gCheese->posX += r5;
}
@@ -341,11 +341,11 @@ static void Task_BossRunManagerMain(void)
}
}
if (manager->unk5 < 7 && gCamera.unk10 > sBossRunCameraYTriggers[manager->unk5] - 600) {
if (manager->unk5 < 7 && gCamera.SA2_LABEL(unk10) > sBossRunCameraYTriggers[manager->unk5] - 600) {
if (manager->unk5 == 6) {
if (manager->unk6 == 0) {
gCamera.unkC = 1;
gCamera.unk8 = 1280;
gCamera.SA2_LABEL(unk8) = 1280;
}
gFinalBossActive = TRUE;
} else {
@@ -180,11 +180,11 @@ static void UpdatePlayerPosition(Sprite_LapTrigger *trigger)
yValue = I(yValue);
gCamera.x += xValue;
gCamera.unk20 += xValue;
gCamera.unk10 += xValue;
gCamera.SA2_LABEL(unk20) += xValue;
gCamera.SA2_LABEL(unk10) += xValue;
gCamera.y += yValue;
gCamera.unk24 += yValue;
gCamera.SA2_LABEL(unk24) += yValue;
gCamera.unk14 += yValue;
}
}
@@ -65,7 +65,7 @@ static void sub_8077F7C(void)
funnelSphere->unk10 -= 0x40;
r6 = (funnelSphere->unk10 >> 2);
if (funnelSphere->keyFrame == 0 && (r6 < 0x40)) {
gCamera.unk50 |= 1;
gCamera.SA2_LABEL(unk50) |= 1;
funnelSphere->keyFrame = 1;
}
@@ -208,7 +208,7 @@ static void sub_80782FC(Sprite_FunnelSphere *funnelSphere)
gPlayer.spriteInfoBody->s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayer.spriteInfoBody->s.frameFlags |= SPRITE_FLAG(PRIORITY, funnelSphere->unk12);
}
gCamera.unk50 &= ~1;
gCamera.SA2_LABEL(unk50) &= ~1;
gCurTask->main = sub_8078414;
}
@@ -282,7 +282,7 @@ static void sub_80784F4(Sprite_FunnelSphere *funnelSphere)
}
gPlayer.qSpeedAirX = 0;
gCamera.unk50 &= ~1;
gCamera.SA2_LABEL(unk50) &= ~1;
m4aSongNumStop(SE_293);
gCurTask->main = sub_8078634;
}
@@ -209,7 +209,7 @@ static void StageGoalToggle_HandleMultiplayerFinish(void)
roomEvent->type = ROOMEVENT_TYPE_REACHED_STAGE_GOAL;
gCurTask->main = StageGoalToggle_PlayerReachedGoal;
gCamera.unk50 |= CAM_MODE_SPECTATOR;
gCamera.SA2_LABEL(unk50) |= CAM_MODE_SPECTATOR;
}
}
@@ -248,7 +248,7 @@ static UNUSED void StageGoalToggle_ForceMultiplayerFinish(void)
roomEvent = CreateRoomEvent();
roomEvent->type = ROOMEVENT_TYPE_REACHED_STAGE_GOAL;
gCurTask->main = StageGoalToggle_PlayerReachedGoal;
gCamera.unk50 |= CAM_MODE_SPECTATOR;
gCamera.SA2_LABEL(unk50) |= CAM_MODE_SPECTATOR;
}
static void StageGoalToggle_PlayerReachedGoal(void)
+7 -7
View File
@@ -378,19 +378,19 @@ NONMATCH("asm/non_matching/game/super_sonic__sub_802BCCC.inc", void sub_802BCCC(
gBossRingsShallRespawn = TRUE;
gCamera.x += someX;
gCamera.unk20 += someX;
gCamera.unk10 += someX;
gCamera.SA2_LABEL(unk20) += someX;
gCamera.SA2_LABEL(unk10) += someX;
gCamera.y += someY;
gCamera.unk24 += someY;
gCamera.SA2_LABEL(unk24) += someY;
gCamera.unk14 += someY;
}
// _0802BDAA
if (sonic->func24 != sub_802C8A0) {
if (ssx < (Q(gCamera.unk10) + Q(8))) {
ssx = Q(gCamera.unk10) + Q(8);
} else if (ssx > (Q(gCamera.unk10) + Q(312))) {
ssx = Q(gCamera.unk10) + Q(312);
if (ssx < (Q(gCamera.SA2_LABEL(unk10)) + Q(8))) {
ssx = Q(gCamera.SA2_LABEL(unk10)) + Q(8);
} else if (ssx > (Q(gCamera.SA2_LABEL(unk10)) + Q(312))) {
ssx = Q(gCamera.SA2_LABEL(unk10)) + Q(312);
}
}
sonic->worldX = ssx;
+169 -97
View File
@@ -3427,26 +3427,25 @@ void SA2_LABEL(sub_8023260)(Player *p)
}
#endif
// ALIGNED UP TO HERE
void SA2_LABEL(sub_80232D0)(Player *p)
{
struct Camera *cam = &gCamera;
s32 qPX = p->qWorldX;
s32 qPY = p->qWorldY;
s32 ix, iy;
s32 ox, oy;
Camera *cam = &gCamera;
s32 qWorldX = p->qWorldX;
s32 qWorldY = p->qWorldY;
s32 unkX, unkY;
#ifndef COLLECT_RINGS_ROM
if (p->playerID == PLAYER_1) {
#if (GAME == GAME_SA2)
if (IS_BOSS_STAGE(gCurrentLevel)) {
if (gCurrentLevel & 0x2) {
ox = gUnknown_080D650C[gCurrentLevel][0];
if ((ox >= 0) && (qPX >= Q(ox))) {
ix = gUnknown_080D661C[gCurrentLevel][0];
iy = gUnknown_080D661C[gCurrentLevel][1];
unkX = SA2_LABEL(gUnknown_080D650C)[gCurrentLevel][0];
if ((unkX >= 0) && (qWorldX >= Q(unkX))) {
s32 ix = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][0];
s32 iy = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][1];
qPX += Q(ix);
qPY += Q(iy);
qWorldX += Q(ix);
qWorldY += Q(iy);
if (gCheese != NULL) {
gCheese->posX += Q(ix);
@@ -3461,59 +3460,91 @@ void SA2_LABEL(sub_80232D0)(Player *p)
gBossRingsShallRespawn = TRUE;
cam->x += ix;
cam->unk20 += ix;
cam->unk10 += ix;
cam->SA2_LABEL(unk20) += ix;
cam->SA2_LABEL(unk10) += ix;
cam->y += iy;
cam->unk24 += iy;
cam->SA2_LABEL(unk24) += iy;
cam->unk14 += iy;
}
}
} else if ((gPlayer.moveState & MOVESTATE_GOAL_REACHED) && (gSpecialRingCount >= SPECIAL_STAGE_REQUIRED_SP_RING_COUNT))
#endif
{
ox = gUnknown_080D650C[gCurrentLevel][0];
if ((ox >= 0) && (qPX >= Q(ox)) && (cam->unk8 != 0)) {
if (!(cam->unk50 & 0x1)) {
s32 ix;
unkX = SA2_LABEL(gUnknown_080D650C)[gCurrentLevel][0];
if ((unkX >= 0) && (qWorldX >= Q(unkX)) && (cam->SA2_LABEL(unk8) != 0) && !(cam->SA2_LABEL(unk50) & 0x1)) {
s32 ix = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][0];
qWorldX += Q(ix);
ix = gUnknown_080D661C[gCurrentLevel][0];
qPX += Q(ix);
cam->x += ix;
cam->unk20 += ix;
cam->unk10 += ix;
if (gCheese != NULL) {
gCheese->posX += Q(ix);
}
#if (GAME == GAME_SA1)
if (gNumSingleplayerCharacters == NUM_SINGLEPLAYER_CHARS_MAX) {
gPartner.qWorldX += Q(ix);
}
#endif
cam->x += ix;
cam->SA2_LABEL(unk20) += ix;
#if (GAME == GAME_SA2)
cam->SA2_LABEL(unk10) += ix;
if (gCheese != NULL) {
gCheese->posX += Q(ix);
}
#endif
}
oy = gUnknown_080D650C[gCurrentLevel][1];
if ((oy >= 0) && (qPY >= Q(oy)) && (cam->unkC != 0)) {
if (!(cam->unk50 & 0x2)) {
s32 iy;
unkY = SA2_LABEL(gUnknown_080D650C)[gCurrentLevel][1];
if ((unkY >= 0) && (qWorldY >= Q(unkY)) && (cam->SA2_LABEL(unkC) != 0) && !(cam->SA2_LABEL(unk50) & 0x2)) {
s32 iy = SA2_LABEL(gUnknown_080D661C)[gCurrentLevel][1];
s32 worldY = iy * CAM_REGION_WIDTH;
qWorldY += Q(worldY);
iy = gUnknown_080D661C[gCurrentLevel][1];
qPY += Q(iy << 8);
cam->y += Q(iy);
cam->unk24 += Q(iy);
if (gCheese != NULL) {
gCheese->posY += Q(iy << 8);
}
#if (GAME == GAME_SA1)
if (gNumSingleplayerCharacters == NUM_SINGLEPLAYER_CHARS_MAX) {
gPartner.qWorldY += Q(worldY);
}
#endif
#if (GAME == GAME_SA1)
// TODO: look at the data and determine if using `worldY` in sa1 was a bug
cam->y += worldY;
cam->SA2_LABEL(unk24) += worldY;
#elif (GAME == GAME_SA2)
cam->y += Q(iy);
cam->SA2_LABEL(unk24) += Q(iy);
if (gCheese != NULL) {
gCheese->posY += Q(worldY);
}
#endif
}
}
}
#endif
if ((p->moveState & (MOVESTATE_80000000 | MOVESTATE_DEAD)) != MOVESTATE_DEAD) {
#if (GAME == GAME_SA2)
s32 camMinY, camMaxY;
#endif
s32 qNoclipWorldX, qNoclipWorldY;
struct Camera *cam2 = &gCamera;
Camera *cam2 = &gCamera;
s32 qPlayerY = p->qWorldY;
if (!(p->moveState & MOVESTATE_80000000)) {
bool32 outOfBounds;
// These blocks are basically the same but the gravity check was swapped in SA2
// TODO: match without gotos
#if (GAME == GAME_SA1)
if (!(gStageFlags & STAGE_FLAG__GRAVITY_INVERTED)) {
if (qPlayerY >= Q(cam2->maxY) - 1) {
outOfBounds = TRUE;
goto lab;
}
} else if ((gStageFlags & STAGE_FLAG__GRAVITY_INVERTED)) {
if (qPlayerY <= Q(cam2->minY)) {
outOfBounds = TRUE;
goto lab;
}
}
outOfBounds = FALSE;
lab:
#elif (GAME == GAME_SA2)
#ifndef COLLECT_RINGS_ROM
if (GRAVITY_IS_INVERTED) {
if (qPlayerY > Q(gCamera.minY)) {
@@ -3543,7 +3574,7 @@ void SA2_LABEL(sub_80232D0)(Player *p)
}
}
#endif
#endif
if (outOfBounds) {
p->moveState |= MOVESTATE_DEAD;
@@ -3555,61 +3586,72 @@ void SA2_LABEL(sub_80232D0)(Player *p)
{
p->qSpeedAirY = -Q(PLAYER_JUMP_HEIGHT);
}
#ifndef COLLECT_RINGS_ROM
qPY = GRAVITY_IS_INVERTED ? Q(cam->minY) : Q(cam->maxY) - 1;
#else
qPY = Q(cam->maxY) - 1;
#endif
}
}
if (IS_BOSS_STAGE(gCurrentLevel)) {
qNoclipWorldX = gBossCameraClampYLower;
qNoclipWorldY = gBossCameraClampYUpper;
} else {
qNoclipWorldX = cam->minY;
qNoclipWorldY = cam->maxY;
}
{
s32 oldQPX = qPX;
s32 oldQPY = qPY;
s32 qMinX = Q(cam->minX);
qPX = CLAMP_32(qPX, qMinX, Q(cam->maxX) - 1);
qPY = CLAMP_32(qPY, Q(qNoclipWorldX), Q(qNoclipWorldY) - 1);
if (qPX != oldQPX) {
p->qSpeedAirX = 0;
p->qSpeedGround = 0;
}
if (qPY != oldQPY) {
p->qSpeedAirY = 0;
p->qSpeedGround = 0;
}
#ifndef COLLECT_RINGS_ROM
if (IS_BOSS_STAGE(gCurrentLevel)) {
s32 qPXMin = (Q(cam->unk10));
if (qPX < qPXMin + Q(8.0)) {
qPX = qPXMin + Q(8.0);
p->qSpeedGround = BOSS_VELOCITY_X;
p->qSpeedAirX = BOSS_VELOCITY_X;
p->moveState &= ~MOVESTATE_FACING_LEFT;
} else if (qPX > (qPXMin + Q(312.0))) {
qPX = (qPXMin + Q(312.0));
p->qSpeedGround = BOSS_VELOCITY_X;
p->qSpeedAirX = BOSS_VELOCITY_X;
#if (GAME == GAME_SA1)
if (!(gStageFlags & STAGE_FLAG__GRAVITY_INVERTED)) {
qWorldY = Q(cam->maxY) - 1;
} else {
qWorldY = Q(cam->minY);
}
#elif (GAME == GAME_SA2)
#ifndef COLLECT_RINGS_ROM
qWorldY = GRAVITY_IS_INVERTED ? Q(cam->minY) : Q(cam->maxY) - 1;
#else
qWorldY = Q(cam->maxY) - 1;
#endif
#endif
}
}
#if (GAME == GAME_SA2)
if (IS_BOSS_STAGE(gCurrentLevel)) {
camMinY = gBossCameraClampYLower;
camMaxY = gBossCameraClampYUpper;
} else {
camMinY = cam->minY;
camMaxY = cam->maxY;
}
#endif
p->qWorldX = qPX;
p->qWorldY = qPY;
qNoclipWorldX = qWorldX;
qNoclipWorldY = qWorldY;
qWorldX = CLAMP(qWorldX, Q(cam->minX), Q(cam->maxX) - 1);
#if (GAME == GAME_SA1)
qWorldY = CLAMP(qWorldY, Q(cam->minY), Q(cam->maxY) - 1);
#elif (GAME == GAME_SA2)
qWorldY = CLAMP(qWorldY, Q(camMinY), Q(camMaxY) - 1);
#endif
if (qWorldX != qNoclipWorldX) {
p->qSpeedAirX = Q(0);
p->qSpeedGround = Q(0);
}
if (qWorldY != qNoclipWorldY) {
p->qSpeedAirY = Q(0);
p->qSpeedGround = Q(0);
}
#if (GAME == GAME_SA2)
#ifndef COLLECT_RINGS_ROM
if (IS_BOSS_STAGE(gCurrentLevel)) {
s32 qPXMin = (Q(cam->SA2_LABEL(unk10)));
if (qWorldX < qPXMin + Q(8.0)) {
qWorldX = qPXMin + Q(8.0);
p->qSpeedGround = BOSS_VELOCITY_X;
p->qSpeedAirX = BOSS_VELOCITY_X;
p->moveState &= ~MOVESTATE_FACING_LEFT;
} else if (qWorldX > (qPXMin + Q(312.0))) {
qWorldX = (qPXMin + Q(312.0));
p->qSpeedGround = BOSS_VELOCITY_X;
p->qSpeedAirX = BOSS_VELOCITY_X;
}
}
#endif
#endif
p->qWorldX = qWorldX;
p->qWorldY = qWorldY;
}
}
@@ -3872,6 +3914,7 @@ NONMATCH("asm/non_matching/game/sa1/stage/Player__sub_8044434.inc", bool32 sub_8
END_NONMATCH
#endif // (GAME == GAME_SA1)
// ALIGNED UP TO HERE
void Player_AirInputControls(Player *p)
{
s32 r5 = p->acceleration * 2;
@@ -3882,6 +3925,9 @@ void Player_AirInputControls(Player *p)
u16 qAirSpeedU = p->qSpeedAirX;
if (p->heldInput & DPAD_LEFT) {
#if (GAME == GAME_SA1) && !defined(NON_MATCHING)
qAirSpeedS = qAirSpeedU;
#endif
if ((p->charState != CHARSTATE_WALK_B) && !(p->moveState & MOVESTATE_2000)) {
p->moveState |= MOVESTATE_FACING_LEFT;
}
@@ -3916,9 +3962,35 @@ void Player_AirInputControls(Player *p)
}
}
}
#if (GAME == GAME_SA1) && !defined(NON_MATCHING)
p->qSpeedAirX = (r5 = qAirSpeedU);
#else
p->qSpeedAirX = qAirSpeedU;
#endif
}
#if (GAME == GAME_SA1)
if ((u16)p->qSpeedAirY > (u16)(-Q(67) - 1)) {
s16 qSpeedAirX = p->qSpeedAirX;
s16 qSpeedAirXFrac = p->qSpeedAirX >> 5;
if (qSpeedAirXFrac < 0) {
qSpeedAirX -= qSpeedAirXFrac;
if (qSpeedAirX > 0) {
qSpeedAirX = 0;
}
p->qSpeedAirX = qSpeedAirX;
} else if (qSpeedAirXFrac > 0) {
qSpeedAirX -= qSpeedAirXFrac;
if (qSpeedAirX < 0)
qSpeedAirX = 0;
p->qSpeedAirX = qSpeedAirX;
}
}
}
#endif
}
#if (GAME == GAME_SA1)
@@ -4523,7 +4595,7 @@ void Task_PlayerHandleDeath(void)
gPlayer.spriteInfoLimbs->s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayer.spriteInfoLimbs->s.frameFlags |= SPRITE_FLAG(PRIORITY, 2);
gCamera.unk50 &= ~0x3;
gCamera.SA2_LABEL(unk50) &= ~0x3;
#ifndef COLLECT_RINGS_ROM
if (gPlayer.character == CHARACTER_CREAM && gCheese != NULL) {
gCheese->posX = gPlayer.qWorldX;
@@ -4657,7 +4729,7 @@ void Task_PlayerMain(void)
p->moveState &= ~MOVESTATE_20;
p->moveState &= ~MOVESTATE_STOOD_ON_OBJ;
p->stoodObj = NULL;
cam->unk50 |= 3;
cam->SA2_LABEL(unk50) |= 3;
#ifndef COLLECT_RINGS_ROM
if (IS_SINGLE_PLAYER) {
gStageFlags |= STAGE_FLAG__ACT_START;
@@ -6971,7 +7043,7 @@ void Player_8027B98(Player *p)
PLAYERFN_UPDATE_UNK2A(p);
gCamera.unk8 -= 56;
gCamera.SA2_LABEL(unk8) -= 56;
}
void Player_8027C5C(Player *p)
@@ -7943,7 +8015,7 @@ void Player_HandleBoostState(Player *p)
if ((!(p->moveState & MOVESTATE_IN_AIR)) && ((ABS(p->qSpeedGround) >= p->topSpeed))) {
if (p->boostSpeed >= playerBoostThresholdTable[p->boostThreshold]) {
p->isBoosting = TRUE;
gCamera.unk8 = 0x400;
gCamera.SA2_LABEL(unk8) = 0x400;
#ifndef COLLECT_RINGS_ROM
CreateBoostModeParticles();
m4aSongNumStart(SE_221);