More align SA1 and SA2 (#203)

* Align InitPlayerHitRingsScatter

* Align InitScatteringRings

* More rings_scatter.c alignment

* More general alignment with SA1

* Align INCREMENT_SCORE macros with SA1

* Align Task_8008DCC with SA1

* Align Demo Manager with SA1

* Some minor cleanup

* Document static PlayerSpriteInfo vars

* Remove nonmatch SA1 code from entities_manager.c and rigns_scatter.c

* Use SA1's matching, yet technically bugged, loop in InitializePlayer

* Fix a potential bug due to memory alignment in Player struct

* Fix crashes due to uninitialized pointers

* Simplify InitializePlayer

Co-authored-by: Oliver Bell <freshollie@gmail.com>

-----------------------------------------

Co-authored-by: Oliver Bell <freshollie@gmail.com>
This commit is contained in:
JaceCearandOliver Bell authored and GitHub committed 2025-02-14 12:31:38 +01:00
1 parent 199c5020f5
commit 1bb658fbbc
28 files changed
+570 -919

No files matched your search

@@ -51,7 +51,7 @@
adds r3, r0, r4
lsls r2, r2, #0x10
asrs r2, r2, #0x10
ldr r1, _0807E760 @ =gUnknown_03005AF0
ldr r1, _0807E760 @ =gPlayerBodyPSI
adds r0, r1, #0
adds r0, #0x38
movs r5, #0
@@ -127,7 +127,7 @@ _0807E752:
.align 2, 0
_0807E758: .4byte gPlayer
_0807E75C: .4byte gCamera
_0807E760: .4byte gUnknown_03005AF0
_0807E760: .4byte gPlayerBodyPSI
_0807E764:
movs r0, #0
_0807E766:
+3 -655
View File
@@ -8,664 +8,12 @@
#define ALLOC_TILES_VARIANT(_animName, _variant) \
VramMalloc(((_animName##_VAR##_variant##_WIDTH / 8) * (_animName##_VAR##_variant##_HEIGHT / 8)))
#if (GAME == GAME_SA1)
//
#define SA1_ANIM_GRIND_EFFECT_WIDTH 32
#define SA1_ANIM_GRIND_EFFECT_HEIGHT 32
#elif (GAME == GAME_SA2)
// 849
#define SA2_ANIM_GRIND_EFFECT_WIDTH 32
#define SA2_ANIM_GRIND_EFFECT_HEIGHT 40
#elif (GAME == GAME_SA3)
// 858
#define ANIM_CHAOMAP_EMERALD_WIDTH 24
#define ANIM_CHAOMAP_EMERALD_HEIGHT 16
// 840
#define ANIM_ANIMAL_WIDTH 16
#define ANIM_ANIMAL_HEIGHT 16
// 866
#define ANIM_SPRING_WIDTH 32
#define ANIM_SPRING_HEIGHT 40
// 866
#define ANIM_DASH_RING_WIDTH 48
#define ANIM_DASH_RING_HEIGHT 48
#define ANIM_DASH_RING_VAR0_WIDTH 16
#define ANIM_DASH_RING_VAR0_HEIGHT 48
#define ANIM_DASH_RING_VAR1_WIDTH 8
#define ANIM_DASH_RING_VAR1_HEIGHT 48
#define ANIM_DASH_RING_VAR2_WIDTH 48
#define ANIM_DASH_RING_VAR2_HEIGHT 16
#define ANIM_DASH_RING_VAR3_WIDTH 48
#define ANIM_DASH_RING_VAR3_HEIGHT 8
#define ANIM_DASH_RING_VAR4_WIDTH 48
#define ANIM_DASH_RING_VAR4_HEIGHT 48
#define ANIM_DASH_RING_VAR5_WIDTH 40
#define ANIM_DASH_RING_VAR5_HEIGHT 40
// 869
#define ANIM_SPIKES_WIDTH 32
#define ANIM_SPIKES_HEIGHT 32
// 870
#define ANIM_RAMP_WIDTH 40
#define ANIM_RAMP_HEIGHT 32
#define ANIM_RAMP_VAR0_WIDTH 40
#define ANIM_RAMP_VAR0_HEIGHT 32
#define ANIM_RAMP_VAR1_WIDTH 40
#define ANIM_RAMP_VAR1_HEIGHT 24
// 872
#define ANIM_ZONE_WARP_WIDTH 48
#define ANIM_ZONE_WARP_HEIGHT 32
// 873
#define ANIM_BOUNCY_BAR_WIDTH 32
#define ANIM_BOUNCY_BAR_HEIGHT 24
// 874
#define ANIM_ROTATING_HANDLE_WIDTH 24
#define ANIM_ROTATING_HANDLE_HEIGHT 24
// 875
#define ANIM_CHECKPOINT_WIDTH 24
#define ANIM_CHECKPOINT_HEIGHT 48
#define ANIM_CHECKPOINT_VAR0_WIDTH 16
#define ANIM_CHECKPOINT_VAR0_HEIGHT 48
#define ANIM_CHECKPOINT_VAR1_WIDTH 24
#define ANIM_CHECKPOINT_VAR1_HEIGHT 48
// 876
#define ANIM_LIFT_WIDTH 8
#define ANIM_LIFT_HEIGHT 24
#define ANIM_LIFT_VAR0_WIDTH 8
#define ANIM_LIFT_VAR0_HEIGHT 24
#define ANIM_LIFT_VAR1_WIDTH 8
#define ANIM_LIFT_VAR1_HEIGHT 8
#define ANIM_LIFT_VAR2_WIDTH 24
#define ANIM_LIFT_VAR2_HEIGHT 16
// 877
#define ANIM_PLATFORM_CRUMBLING_1_WIDTH 48
#define ANIM_PLATFORM_CRUMBLING_1_HEIGHT 32
// 878
#define ANIM_TRAMPOLINE_WIDTH 48
#define ANIM_TRAMPOLINE_HEIGHT 32
// 878
#define ANIM_BUTTON_BLUE_WIDTH 24
#define ANIM_BUTTON_BLUE_HEIGHT 24
// 880
#define ANIM_BUTTON_SPRING_1_VAR0_WIDTH 32
#define ANIM_BUTTON_SPRING_1_VAR0_HEIGHT 40
#define ANIM_BUTTON_SPRING_1_VAR5_WIDTH 40
#define ANIM_BUTTON_SPRING_1_VAR5_HEIGHT 24
#define ANIM_BUTTON_SPRING_1_VAR10_WIDTH 32
#define ANIM_BUTTON_SPRING_1_VAR10_HEIGHT 32
#define ANIM_BUTTON_SPRING_1_VAR15_WIDTH 24
#define ANIM_BUTTON_SPRING_1_VAR15_HEIGHT 24
// 882
#define ANIM_DECO_ROCK_WIDTH 48
#define ANIM_DECO_ROCK_HEIGHT 32
// 883
#define ANIM_FLAT_SPRING_WIDTH 32
#define ANIM_FLAT_SPRING_HEIGHT 32
// 884
#define ANIM_PLATFORM_RAISING_WHEEL_WIDTH 32
#define ANIM_PLATFORM_RAISING_WHEEL_HEIGHT 24
#define ANIM_PLATFORM_RAISING_WHEEL_PLATFORM_WIDTH 24
#define ANIM_PLATFORM_RAISING_WHEEL_PLATFORM_HEIGHT 24
// 886
#define ANIM_ACCORDION_SPRING_2_WIDTH 32
#define ANIM_ACCORDION_SPRING_2_HEIGHT 24
// 889
#define ANIM_PLATFORM_2_WIDTH 48
#define ANIM_PLATFORM_2_HEIGHT 24
// 886
#define ANIM_PLATFORM_CRUMBLING_2_WIDTH 48
#define ANIM_PLATFORM_CRUMBLING_2_HEIGHT 24
// 898
#define ANIM_PLATFORM_ON_A_PATH_3_WIDTH 56
#define ANIM_PLATFORM_ON_A_PATH_3_HEIGHT 24
// 891
#define ANIM_BUNGEE_CORD_WIDTH 8
#define ANIM_BUNGEE_CORD_HEIGHT 8
#define ANIM_BUNGEE_CORD_VAR0_WIDTH 8
#define ANIM_BUNGEE_CORD_VAR0_HEIGHT 8
// 892
#define ANIM_SUNSET_BRIDGE_WIDTH 24
#define ANIM_SUNSET_BRIDGE_HEIGHT 32
// 893
#define ANIM_PLATFORM_2_2_WIDTH 48
#define ANIM_PLATFORM_2_2_HEIGHT 16
#define ANIM_PLATFORM_2_2_VAR0_WIDTH 48
#define ANIM_PLATFORM_2_2_VAR0_HEIGHT 16
// 894
#define ANIM_WAGGLE_COIL_WIDTH 48
#define ANIM_WAGGLE_COIL_HEIGHT 56
// 900
#define ANIM_PLATFORM_3_0_WIDTH (48 / 2)
#define ANIM_PLATFORM_3_0_HEIGHT 24
// 901
#define ANIM_SUCTION_3_VERTICAL_WIDTH 24
#define ANIM_SUCTION_3_VERTICAL_HEIGHT 56
// 902
#define ANIM_SUCTION_3_HORIZONTAL_WIDTH 56
#define ANIM_SUCTION_3_HORIZONTAL_HEIGHT 24
// 903
#define ANIM_DEATH_CRUSHER_SPIKED_WIDTH 24
#define ANIM_DEATH_CRUSHER_SPIKED_HEIGHT 80
// 904
#define ANIM_DEATH_CRUSHER_NO_LED_WIDTH 24
#define ANIM_DEATH_CRUSHER_NO_LED_HEIGHT 48
// 905
#define ANIM_DEATH_CRUSHER_WIDTH 24
#define ANIM_DEATH_CRUSHER_HEIGHT 48
// 907
#define ANIM_PLATFORM_CRUMBLING_3_WIDTH 48
#define ANIM_PLATFORM_CRUMBLING_3_HEIGHT 48
// 908 - x-mirrored
#define ANIM_PROPELLER_BUTTON_PLATFORM_WIDTH (64 / 2)
#define ANIM_PROPELLER_BUTTON_PLATFORM_HEIGHT 48
// 910
#define ANIM_WATER_CANNON_WIDTH 32
#define ANIM_WATER_CANNON_HEIGHT 48
// 911
#define ANIM_FACTORY_RING_WIDTH 48
#define ANIM_FACTORY_RING_HEIGHT 48
// 912
#define ANIM_SPECIAL_SPRING_WIDTH 32
#define ANIM_SPECIAL_SPRING_HEIGHT 48
// 913
#define ANIM_BONUS_UFO_WIDTH 24
#define ANIM_BONUS_UFO_HEIGHT 48
// 914
#define ANIM_BONUS_UFO_RAY_WIDTH 24
#define ANIM_BONUS_UFO_RAY_HEIGHT 56
// 915
#define ANIM_ROCKET_WIDTH 48
#define ANIM_ROCKET_HEIGHT 48
#define ANIM_ROCKET_VAR0_WIDTH 16
#define ANIM_ROCKET_VAR0_HEIGHT 8
#define ANIM_ROCKET_VAR1_WIDTH 16
#define ANIM_ROCKET_VAR1_HEIGHT 8
#define ANIM_ROCKET_VAR2_WIDTH 8
#define ANIM_ROCKET_VAR2_HEIGHT 8
#define ANIM_ROCKET_VAR3_WIDTH 8
#define ANIM_ROCKET_VAR3_HEIGHT 8
#define ANIM_ROCKET_VAR4_WIDTH 8
#define ANIM_ROCKET_VAR4_HEIGHT 8
#define ANIM_ROCKET_VAR5_WIDTH 8
#define ANIM_ROCKET_VAR5_HEIGHT 8
#define ANIM_ROCKET_VAR6_WIDTH 8
#define ANIM_ROCKET_VAR6_HEIGHT 8
// 916
#define ANIM_FERRIS_WHEEL_HEIGHT 8
#define ANIM_FERRIS_WHEEL_WIDTH 8
#define ANIM_FERRIS_WHEEL_VAR0_HEIGHT 8
#define ANIM_FERRIS_WHEEL_VAR0_WIDTH 8
#define ANIM_FERRIS_WHEEL_VAR1_HEIGHT 8
#define ANIM_FERRIS_WHEEL_VAR1_WIDTH 8
// 917
#define ANIM_TOY_BALLOON_WIDTH 32
#define ANIM_TOY_BALLOON_HEIGHT 48
// 918 (x-mirrored)
#define ANIM_SPRING_IN_A_BOX_WIDTH (64 / 2)
#define ANIM_SPRING_IN_A_BOX_HEIGHT 64
// 919
#define ANIM_PANDA_CART_WIDTH 48
#define ANIM_PANDA_CART_HEIGHT 40
// 920
#define ANIM_PENDULUM_WIDTH 40
#define ANIM_PENDULUM_HEIGHT 40
#define ANIM_PENDULUM_VAR0_WIDTH 40
#define ANIM_PENDULUM_VAR0_HEIGHT 40
#define ANIM_PENDULUM_VAR1_WIDTH 8
#define ANIM_PENDULUM_VAR1_HEIGHT 8
// 921 (x-mirrored)
#define ANIM_PLATFORM_SPIKED_WIDTH 32
#define ANIM_PLATFORM_SPIKED_HEIGHT 48
// 922
#define ANIM_ICE_SPIKE_WIDTH 32
#define ANIM_ICE_SPIKE_HEIGHT 32
// 923
#define ANIM_ICE_LAUNCHER_WIDTH 48
#define ANIM_ICE_LAUNCHER_HEIGHT 64
// 924
#define ANIM_WINDUP_BLOCK_WIDTH 24
#define ANIM_WINDUP_BLOCK_HEIGHT 24
#define ANIM_WINDUP_BLOCK_VAR0_WIDTH 24
#define ANIM_WINDUP_BLOCK_VAR0_HEIGHT 24
#define ANIM_WINDUP_BLOCK_VAR1_WIDTH 24
#define ANIM_WINDUP_BLOCK_VAR1_HEIGHT 24
#define ANIM_WINDUP_BLOCK_VAR2_WIDTH 24
#define ANIM_WINDUP_BLOCK_VAR2_HEIGHT 24
#define ANIM_WINDUP_BLOCK_VAR3_WIDTH 24
#define ANIM_WINDUP_BLOCK_VAR3_HEIGHT 24
// 925
#define ANIM_MINECART_WIDTH 64
#define ANIM_MINECART_HEIGHT 64
#define ANIM_MINECART_VAR0_WIDTH 64
#define ANIM_MINECART_VAR0_HEIGHT 64
#define ANIM_MINECART_VAR1_WIDTH 64
#define ANIM_MINECART_VAR1_HEIGHT 64
#define ANIM_MINECART_VAR2_WIDTH 16
#define ANIM_MINECART_VAR2_HEIGHT 16
#define ANIM_MINECART_VAR3_WIDTH 8
#define ANIM_MINECART_VAR3_HEIGHT 8
#define ANIM_MINECART_VAR4_WIDTH 8
#define ANIM_MINECART_VAR4_HEIGHT 8
// 926
#define ANIM_AIR_BUBBLES_WIDTH 24
#define ANIM_AIR_BUBBLES_HEIGHT 24
#define ANIM_AIR_BUBBLES_VAR0_WIDTH 24
#define ANIM_AIR_BUBBLES_VAR0_HEIGHT 24
#define ANIM_AIR_BUBBLES_VAR1_WIDTH 8
#define ANIM_AIR_BUBBLES_VAR1_HEIGHT 8
#define ANIM_AIR_BUBBLES_VAR2_WIDTH 24
#define ANIM_AIR_BUBBLES_VAR2_HEIGHT 24
// 927
#define ANIM_ATTACHED_PLATFORM_WIDTH 48
#define ANIM_ATTACHED_PLATFORM_HEIGHT 16
#define ANIM_ATTACHED_PLATFORM_VAR0_WIDTH 48
#define ANIM_ATTACHED_PLATFORM_VAR0_HEIGHT 16
#define ANIM_ATTACHED_PLATFORM_VAR1_WIDTH 16
#define ANIM_ATTACHED_PLATFORM_VAR1_HEIGHT 16
#define ANIM_ATTACHED_PLATFORM_VAR2_WIDTH 8
#define ANIM_ATTACHED_PLATFORM_VAR2_HEIGHT 8
// 929
#define ANIM_BOULDER_WIDTH 40
#define ANIM_BOULDER_HEIGHT 40
#define ANIM_BOULDER_VAR0_WIDTH 40
#define ANIM_BOULDER_VAR0_HEIGHT 40
#define ANIM_BOULDER_VAR1_WIDTH 16
#define ANIM_BOULDER_VAR1_HEIGHT 16
#define ANIM_BOULDER_VAR2_WIDTH 8
#define ANIM_BOULDER_VAR2_HEIGHT 8
// 931
#define ANIM_UFO_PLATFORM_WIDTH 48
#define ANIM_UFO_PLATFORM_HEIGHT 24
// 930
#define ANIM_CLOSING_WALL_WIDTH 72
#define ANIM_CLOSING_WALL_HEIGHT 24
// 933
#define ANIM_FALL_PLATFORM_CA_WIDTH 48
#define ANIM_FALL_PLATFORM_CA_HEIGHT 16
// 934
#define ANIM_WATER_CANNON_SPLASH_WIDTH 48
#define ANIM_WATER_CANNON_SPLASH_HEIGHT 40
// 935
#define ANIM_PLATFORM_CRUMBLING_7_WIDTH 48
#define ANIM_PLATFORM_CRUMBLING_7_HEIGHT 40
// 936
#define ANIM_SPRING_6_WIDTH 24
#define ANIM_SPRING_6_HEIGHT 40
// 938
#define ANIM_PLATFORM_CRUMBLING_6_WIDTH 48
#define ANIM_PLATFORM_CRUMBLING_6_HEIGHT 24
// 939
#define ANIM_SPRING_PLATFORM_6_WIDTH 24
#define ANIM_SPRING_PLATFORM_6_HEIGHT 64
// 940
#define ANIM_MAZE_WIDTH 48
#define ANIM_MAZE_HEIGHT 64
#define ANIM_MAZE_VAR0_WIDTH 48
#define ANIM_MAZE_VAR0_HEIGHT 64
#define ANIM_MAZE_VAR1_WIDTH 48
#define ANIM_MAZE_VAR1_HEIGHT 64
#define ANIM_MAZE_VAR2_WIDTH 48
#define ANIM_MAZE_VAR2_HEIGHT 64
#define ANIM_MAZE_VAR3_WIDTH 64
#define ANIM_MAZE_VAR3_HEIGHT 48
#define ANIM_MAZE_VAR4_WIDTH 64
#define ANIM_MAZE_VAR4_HEIGHT 48
#define ANIM_MAZE_VAR5_WIDTH 64
#define ANIM_MAZE_VAR5_HEIGHT 48
#define ANIM_MAZE_VAR6_WIDTH 24
#define ANIM_MAZE_VAR6_HEIGHT 24
#define ANIM_MAZE_VAR7_WIDTH 48
#define ANIM_MAZE_VAR7_HEIGHT 56
#define ANIM_MAZE_VAR8_WIDTH 56
#define ANIM_MAZE_VAR8_HEIGHT 48
// 942
#define ANIM_PLATFORM_ON_A_PATH_6_WIDTH 56
#define ANIM_PLATFORM_ON_A_PATH_6_HEIGHT 24
// 945
#define ANIM_MUD_FX_WIDTH 48
#define ANIM_MUD_FX_HEIGHT 24
#define ANIM_MUD_FX_CHAOS_ANGEL_WIDTH 48
#define ANIM_MUD_FX_CHAOS_ANGEL_HEIGHT 24
// 948
#define ANIM_GOAL_RING_WIDTH 24
#define ANIM_GOAL_RING_HEIGHT 24
#define ANIM_GOAL_RING_VAR8_WIDTH 24 // Sparkle effect
#define ANIM_GOAL_RING_VAR8_HEIGHT 16
// 949
#define ANIM_SUCTION_VERTICAL_WIDTH 24
#define ANIM_SUCTION_VERTICAL_HEIGHT 56
// 950
#define ANIM_SUCTION_HORIZONTAL_WIDTH 56
#define ANIM_SUCTION_HORIZONTAL_HEIGHT 24
// 951
#define ANIM_PLATFORM_CRUMBLING_4_WIDTH 48
#define ANIM_PLATFORM_CRUMBLING_4_HEIGHT 24
// 952
#define ANIM_PLATFORM_CRUMBLING_5_WIDTH 48
#define ANIM_PLATFORM_CRUMBLING_5_HEIGHT 32
// 955
#define ANIM_SUCTION_STREAM_HORIZONTAL_WIDTH 24
#define ANIM_SUCTION_STREAM_HORIZONTAL_HEIGHT 56
// 956
#define ANIM_SUCTION_STREAM_VERTICAL_WIDTH 56
#define ANIM_SUCTION_STREAM_VERTICAL_HEIGHT 24
// 969
#define ANIM_WINDUP_BLOCK_7_WIDTH 24
#define ANIM_WINDUP_BLOCK_7_HEIGHT 24
#define ANIM_WINDUP_BLOCK_7_VAR0_WIDTH 24
#define ANIM_WINDUP_BLOCK_7_VAR0_HEIGHT 24
#define ANIM_WINDUP_BLOCK_7_VAR1_WIDTH 8
#define ANIM_WINDUP_BLOCK_7_VAR1_HEIGHT 24
#define ANIM_WINDUP_BLOCK_7_VAR2_WIDTH 24
#define ANIM_WINDUP_BLOCK_7_VAR2_HEIGHT 24
#define ANIM_WINDUP_BLOCK_7_VAR3_WIDTH 24
#define ANIM_WINDUP_BLOCK_7_VAR3_HEIGHT 8
// 976
#define ANIM_TOY_BALLOON_POPPED_WIDTH 32
#define ANIM_TOY_BALLOON_POPPED_HEIGHT 48
// 976
#define ANIM_OMOCHAO0_WIDTH 24
#define ANIM_OMOCHAO0_HEIGHT 24
// 977
#define ANIM_OMOCHAO1_WIDTH 24
#define ANIM_OMOCHAO1_HEIGHT 24
// 978
#define ANIM_OMOCHAO2_WIDTH 24
#define ANIM_OMOCHAO2_HEIGHT 24
// 979
#define ANIM_OMOCHAO3_WIDTH 24
#define ANIM_OMOCHAO3_HEIGHT 24
// 980
#define ANIM_OMOCHAO4_WIDTH 24
#define ANIM_OMOCHAO4_HEIGHT 24
// 981
#define ANIM_OMOCHAO5_WIDTH 24
#define ANIM_OMOCHAO5_HEIGHT 24
// 983
#define ANIM_ACT_RING_WIDTH 32
#define ANIM_ACT_RING_HEIGHT 32
#define ANIM_ACT_RING_VAR0_WIDTH 32
#define ANIM_ACT_RING_VAR0_HEIGHT 32
#define ANIM_ACT_RING_VAR1_WIDTH 32
#define ANIM_ACT_RING_VAR1_HEIGHT 32
#define ANIM_ACT_RING_VAR2_WIDTH 32
#define ANIM_ACT_RING_VAR2_HEIGHT 32
// "Crown" signalling completion
#define ANIM_ACT_RING_VAR3_WIDTH 24
#define ANIM_ACT_RING_VAR3_HEIGHT 16
// 984
#define ANIM_SPRING_PLATFORM_4_WIDTH 24
#define ANIM_SPRING_PLATFORM_4_HEIGHT 64
// 986
#define ANIM_SLOW_LIFT_7_WIDTH (112 / 2)
#define ANIM_SLOW_LIFT_7_HEIGHT 24
// 987
#define ANIM_SPRING_4_WIDTH 32
#define ANIM_SPRING_4_HEIGHT 40
// 995
#define ANIM_BUTTON_SPRING_6_VAR0_WIDTH 32
#define ANIM_BUTTON_SPRING_6_VAR0_HEIGHT 40
#define ANIM_BUTTON_SPRING_6_VAR5_WIDTH 40
#define ANIM_BUTTON_SPRING_6_VAR5_HEIGHT 24
#define ANIM_BUTTON_SPRING_6_VAR10_WIDTH 32
#define ANIM_BUTTON_SPRING_6_VAR10_HEIGHT 32
// 997
#define ANIM_PLATFORM_BONUS_WIDTH 48
#define ANIM_PLATFORM_BONUS_HEIGHT 48
#define ANIM_PLATFORM_BONUS_VAR0_WIDTH 48
#define ANIM_PLATFORM_BONUS_VAR0_HEIGHT 48
#define ANIM_PLATFORM_BONUS_VAR1_WIDTH 48
#define ANIM_PLATFORM_BONUS_VAR1_HEIGHT 24
// 1004
#define ANIM_CHAO_SITTING_WIDTH 32
#define ANIM_CHAO_SITTING_HEIGHT 32
// 1042
#define ANIM_UI_PROMPT_BUTTON_WIDTH 16
#define ANIM_UI_PROMPT_BUTTON_HEIGHT 16
// 1059
#define ANIM_BONUS_UI_TIMER_DIGITS_WIDTH 8
#define ANIM_BONUS_UI_TIMER_DIGITS_HEIGHT 16
// 1063
#define ANIM_BONUS_UI_FLOWER_WIDTH 16
#define ANIM_BONUS_UI_FLOWER_HEIGHT 24
// 1064
#define ANIM_BONUS_UI_BAR_WIDTH 16
#define ANIM_BONUS_UI_BAR_HEIGHT 16
// 1065
#define ANIM_BONUS_UI_X_WIDTH 48
#define ANIM_BONUS_UI_X_HEIGHT 32
#define ANIM_BONUS_UI_X_VAR0_WIDTH 16
#define ANIM_BONUS_UI_X_VAR0_HEIGHT 16
#define ANIM_BONUS_UI_X_VAR1_WIDTH 48
#define ANIM_BONUS_UI_X_VAR1_HEIGHT 32
// 1154
#define ANIM_BONUS_CAPSULE_WIDTH 56
#define ANIM_BONUS_CAPSULE_HEIGHT 72
// 1155
#define ANIM_BONUS_CAPSULE_POINTS_WIDTH 24
#define ANIM_BONUS_CAPSULE_POINTS_HEIGHT 24
// 1156
#define ANIM_BONUS_CAPSULE_SWITCH_WIDTH 24
#define ANIM_BONUS_CAPSULE_SWITCH_HEIGHT 16
// 1160
#define ANIM_BONUS_UI_SCORE_WIDTH 32
#define ANIM_BONUS_UI_SCORE_HEIGHT 16
// Enemies
// 1166
#define ANIM_SPINNER_WIDTH 48
#define ANIM_SPINNER_HEIGHT 32
// 1168
#define ANIM_CONDOR_WIDTH 48
#define ANIM_CONDOR_HEIGHT 40
// 1168
#define ANIM_AKATENTO_WIDTH 32
#define ANIM_AKATENTO_HEIGHT 24
// 1169
#define ANIM_AOTENTO_WIDTH 32
#define ANIM_AOTENTO_HEIGHT 32
// 1171
#define ANIM_APE_WIDTH 40
#define ANIM_APE_HEIGHT 32
#define ANIM_APE_VAR2_WIDTH 16
#define ANIM_APE_VAR2_HEIGHT 16
// 1172
#define ANIM_APE_PROJ_WIDTH 16
#define ANIM_APE_PROJ_HEIGHT 16
// 1173
#define ANIM_FROG_WIDTH 32
#define ANIM_FROG_HEIGHT 48
// 1174
#define ANIM_MINIMOLE_WIDTH 48
#define ANIM_MINIMOLE_HEIGHT 24
#define ANIM_MINIMOLE_VAR0_WIDTH 48
#define ANIM_MINIMOLE_VAR0_HEIGHT 24
#define ANIM_MINIMOLE_VAR1_WIDTH 32
#define ANIM_MINIMOLE_VAR1_HEIGHT 8
// 1175
#define ANIM_BUZZER_WIDTH 48
#define ANIM_BUZZER_HEIGHT 32
// 1176
#define ANIM_BUZZER_PROJ_WIDTH 16
#define ANIM_BUZZER_PROJ_HEIGHT 16
// 1178
#define ANIM_TAKKON_WIDTH 32
#define ANIM_TAKKON_HEIGHT 48
// 1177
#define ANIM_JOUSUN_WIDTH 40
#define ANIM_JOUSUN_HEIGHT 32
// 1180
#define ANIM_TAKKON_PROJ_WIDTH 24
#define ANIM_TAKKON_PROJ_HEIGHT 24
#define ANIM_TAKKON_PROJ_VAR0_WIDTH 8
#define ANIM_TAKKON_PROJ_VAR0_HEIGHT 24
#define ANIM_TAKKON_PROJ_VAR4_WIDTH 24
#define ANIM_TAKKON_PROJ_VAR4_HEIGHT 24
// 1182
#define ANIM_GAOGAO_WIDTH 32
#define ANIM_GAOGAO_HEIGHT 32
// 1187
#define ANIM_GINPE_WIDTH 24
#define ANIM_GINPE_HEIGHT 32
// 1187
#define ANIM_GINPE_PROJ_WIDTH 8
#define ANIM_GINPE_PROJ_HEIGHT 8
// 1191
#define ANIM_YADOKK_WIDTH 32
#define ANIM_YADOKK_HEIGHT 32
#define ANIM_YADOKK_VAR2_WIDTH 32
#define ANIM_YADOKK_VAR2_HEIGHT 32
// 1315
#define ANIM_ITEM_BOX_TYPE_WIDTH 16
#define ANIM_ITEM_BOX_TYPE_HEIGHT 16
// 1316
#define ANIM_ITEM_BOX_WIDTH 32
#define ANIM_ITEM_BOX_HEIGHT 32
// 1338
#define ANIM_ITEM_BOX_CLOUD_EFFECT_WIDTH 32
#define ANIM_ITEM_BOX_CLOUD_EFFECT_HEIGHT 32
// 1139
#define ANIM_CONDOR_PROJ_EXPLOSION_WIDTH 32
#define ANIM_CONDOR_PROJ_EXPLOSION_HEIGHT 32
// 1344
#define ANIM_ICE_SHIVER_WIDTH 16
#define ANIM_ICE_SHIVER_HEIGHT 16
// 1348
#define ANIM_SPECIAL_KEY_WIDTH 32
#define ANIM_SPECIAL_KEY_HEIGHT 32
// 1423
#define ANIM_LIFE_ICONS_WIDTH 16
#define ANIM_LIFE_ICONS_HEIGHT 16
#define ANIM_LIFE_ICONS_VAR0_WIDTH 16
#define ANIM_LIFE_ICONS_VAR0_HEIGHT 16
#define ANIM_LIFE_ICONS_VAR1_WIDTH 16
#define ANIM_LIFE_ICONS_VAR1_HEIGHT 16
#define ANIM_LIFE_ICONS_VAR2_WIDTH 16
#define ANIM_LIFE_ICONS_VAR2_HEIGHT 16
#define ANIM_LIFE_ICONS_VAR3_WIDTH 16
#define ANIM_LIFE_ICONS_VAR3_HEIGHT 16
#define ANIM_LIFE_ICONS_VAR4_WIDTH 16
#define ANIM_LIFE_ICONS_VAR4_HEIGHT 16
#define ANIM_LIFE_ICONS_VAR5_WIDTH 16
#define ANIM_LIFE_ICONS_VAR5_HEIGHT 16
#define ANIM_LIFE_ICONS_VAR6_WIDTH 16
#define ANIM_LIFE_ICONS_VAR6_HEIGHT 16
#endif
// 1044
#define ANIM_DEMO_PLAY_WIDTH 112
#define ANIM_DEMO_PLAY_HEIGHT 16
#endif // GUARD_ANIM_SIZES_H
+1 -1
View File
@@ -594,7 +594,7 @@
#define SA2_ANIM_SOUNDTEST_PLATFORM 972
#define SA2_ANIM_SOUNDTEST_CLAP_FORWARD 973
#define SA2_ANIM_DEMO_PLAY 1044
#define ANIM_DEMO_PLAY 1044
#define SA2_ANIM_1045 1045
#define SA2_ANIM_COPYRIGHT_INFO_TITLE_SCREEN 1046
#define SA2_ANIM_TIME_ATTACK_DIGITS 1047
+11 -4
View File
@@ -124,16 +124,23 @@ union MultiSioData {
// TODO: Have we defined this somewhere else already?
#define MAP_LAYER_COUNT 2
// Thanks @MainMemory_ for figuring out how collision works!
#if (GAME == GAME_SA1)
typedef u16 collPxDim_t;
#else
typedef u32 collPxDim_t;
#endif
// Thanks @MainMemory_ for figuring out how collision is stored!
typedef struct {
/* 0x00 */ const s8 *height_map;
/* 0x04 */ const u8 *tile_rotation;
/* 0x08 */ const u16 *metatiles;
/* 0x0C */ const u16 *map[MAP_LAYER_COUNT];
/* 0x0C */ const MetatileIndexType *map[MAP_LAYER_COUNT];
/* 0x14 */ const u16 *flags;
/* 0x18 */ u16 levelX, levelY;
/* 0x1C */ u32 pxWidth; // u16 in SA1!
/* 0x20 */ u32 pxHeight; // u16 in SA1!
/* 0x1C */ collPxDim_t pxWidth, pxHeight;
// unk20/unk22 are not in SA1
} Collision;
struct Unk_03003674_1_Sub {
+5 -4
View File
@@ -157,10 +157,11 @@ u32 sub_800DF38(Sprite *, s32, s32, Player *);
#define ENEMY_CROSSED_BOTTOM_BORDER(_enemy, _mapEntity) ENEMY_CROSSED_BOTTOM_BORDER_RAW(_enemy, _mapEntity, I(_enemy->offsetY))
#define ENEMY_CLAMP_TO_GROUND_INNER(_enemy, _unknownBool, _task) \
sub_801F100(I(_enemy->spawnY + _enemy->offsetY), I(_enemy->spawnX + _enemy->offsetX), _unknownBool, 8, _task);
SA2_LABEL(sub_801F100)(I(_enemy->spawnY + _enemy->offsetY), I(_enemy->spawnX + _enemy->offsetX), _unknownBool, 8, _task);
#define ENEMY_CLAMP_TO_GROUND_INNER_X_FIRST(_enemy, _unknownBool) \
sub_801F100(I(_enemy->spawnX + _enemy->offsetX), I(_enemy->spawnY + _enemy->offsetY), _unknownBool, 8, sub_801EC3C);
SA2_LABEL(sub_801F100) \
(I(_enemy->spawnX + _enemy->offsetX), I(_enemy->spawnY + _enemy->offsetY), _unknownBool, 8, SA2_LABEL(sub_801EC3C));
#define ENEMY_CLAMP_TO_GROUND_RAW(_enemy, _unknownBool, _p) \
{ \
@@ -169,7 +170,7 @@ u32 sub_800DF38(Sprite *, s32, s32, Player *);
\
if (delta < 0) { \
_enemy->offsetY += Q(delta); \
delta = ENEMY_CLAMP_TO_GROUND_INNER(_enemy, _unknownBool, sub_801EC3C); \
delta = ENEMY_CLAMP_TO_GROUND_INNER(_enemy, _unknownBool, SA2_LABEL(sub_801EC3C)); \
} \
\
if (delta > 0) { \
@@ -186,7 +187,7 @@ u32 sub_800DF38(Sprite *, s32, s32, Player *);
\
if (delta < 0) { \
_enemy->offsetY -= Q(delta); \
delta = ENEMY_CLAMP_TO_GROUND_INNER(_enemy, _unknownBool, sub_801EC3C); \
delta = ENEMY_CLAMP_TO_GROUND_INNER(_enemy, _unknownBool, SA2_LABEL(sub_801EC3C)); \
} \
\
if (delta > 0) { \
-2
View File
@@ -1,8 +1,6 @@
#ifndef GUARD_UNKNOWN_OBJECT_6998_H
#define GUARD_UNKNOWN_OBJECT_6998_H
#include "global.h"
void CreateHeartParticles(void);
#endif // GUARD_UNKNOWN_OBJECT_6998_H
+2 -3
View File
@@ -10,7 +10,6 @@ typedef s16 CamCoord;
typedef s32 CamCoord;
#endif
// TODO: Move TILE_WIDTH into "include/tilemap.h"
#define TILE_WIDTH 8
#define CAM_REGION_WIDTH 256
#define TILES_PER_METATILE_AXIS 12
@@ -26,7 +25,7 @@ typedef void (*BgUpdate)(s32, s32);
// NOTE: This was copy-pasted from SA2.
// There are type differences for members
struct Camera {
typedef struct Camera {
/* 0x00|0x04 */ CamCoord x;
/* 0x02|0x04 */ CamCoord y;
#if (GAME == GAME_SA1)
@@ -73,7 +72,7 @@ struct Camera {
/* 0x64 */ s16 unk64;
/* 0x66 */ u8 spectatorTarget;
#endif
}; /* size 0x80(in SA2) */
} Camera; /* size 0x80(in SA2) */
extern struct Camera gCamera;
+27 -20
View File
@@ -212,56 +212,63 @@ extern struct InputCounters gNewInputCounters[32];
extern u8 gUnknown_030055D8;
#if (GAME == GAME_SA1)
#define SET_LIVES_A(lives) (lives)
#if (GAME == GAME_SA1) && !defined(BUG_FIX)
#define LIVES_BOUND_CHECK_A(lives) (lives)
#define LIVES_BOUND_CHECK_B(lives) (lives)
#define NEW_LIVE_COUNT(_type, _varname, _inc) (gNumLives += 1)
#define BOUND_CHK_VARNAME gNumLives
#else
#define SET_LIVES_A(lives) \
#define LIVES_BOUND_CHECK_A(lives) \
({ \
if ((lives) > 255) \
(lives) = 255; \
gNumLives = (lives); \
})
#endif
// Sometimes this variant was used
#define SET_LIVES_B(lives) \
#define LIVES_BOUND_CHECK_B(lives) \
({ \
if (lives > 255) { \
gNumLives = 255; \
} else { \
gNumLives = lives; \
}; \
});
} \
})
#define INCREMENT_SCORE_BASE(incVal, restartMusic, SetLives) \
#define NEW_LIVE_COUNT(_type, _varname, _inc) \
_type _varname = divResA - divResB; \
_varname += _inc;
#define BOUND_CHK_VARNAME lives
#endif
#define INCREMENT_SCORE_BASE(_inc, restartMusic, BoundCheck) \
{ \
s32 divResA, divResB; \
s32 oldScore = gLevelScore; \
gLevelScore += incVal; \
gLevelScore += _inc; \
\
divResA = Div(gLevelScore, 50000); \
divResB = Div(oldScore, 50000); \
\
if ((divResA != divResB) && (gGameMode == GAME_MODE_SINGLE_PLAYER)) { \
u16 lives = divResA - divResB; \
lives += gNumLives; \
\
SetLives(lives); \
NEW_LIVE_COUNT(u16, BOUND_CHK_VARNAME, gNumLives); \
BoundCheck(BOUND_CHK_VARNAME); \
\
if (restartMusic) \
gMusicManagerState.unk3 = 0x10 | 0x0; \
} \
}
#define INCREMENT_SCORE_A(incVal) INCREMENT_SCORE_BASE(incVal, FALSE, SET_LIVES_A)
#define INCREMENT_SCORE(incVal) INCREMENT_SCORE_BASE(incVal, TRUE, SET_LIVES_A)
#define INCREMENT_SCORE_B(incVal) INCREMENT_SCORE_BASE(incVal, TRUE, SET_LIVES_B)
#define INCREMENT_SCORE_A(_inc) INCREMENT_SCORE_BASE(_inc, FALSE, LIVES_BOUND_CHECK_A)
#define INCREMENT_SCORE(_inc) INCREMENT_SCORE_BASE(_inc, TRUE, LIVES_BOUND_CHECK_A)
#define INCREMENT_SCORE_B(_inc) INCREMENT_SCORE_BASE(_inc, TRUE, LIVES_BOUND_CHECK_B)
#define INCREMENT_RINGS(incVal) \
#define INCREMENT_RINGS(_inc) \
{ \
s32 prevLives, newLives; \
s32 oldRings = gRingCount; \
gRingCount += incVal; \
gRingCount += _inc; \
\
if (!(IS_EXTRA_STAGE(gCurrentLevel))) { \
newLives = Div(gRingCount, 100); \
@@ -270,7 +277,7 @@ extern u8 gUnknown_030055D8;
if ((newLives != prevLives) && (gGameMode == GAME_MODE_SINGLE_PLAYER)) { \
u16 lives = gNumLives + 1; \
\
SET_LIVES_A(lives); \
gNumLives = LIVES_BOUND_CHECK_A(lives); \
\
gMusicManagerState.unk3 = 0x10 | 0x0; \
} \
+15 -2
View File
@@ -13,8 +13,8 @@ typedef struct {
/*0x3C */ Hitbox reserved; // TODO: Maybe 3 hitboxes (Player, Action, Shield)?
} PlayerSpriteInfo; /* size: 0x44 */
extern PlayerSpriteInfo gUnknown_03005AA0;
extern PlayerSpriteInfo gUnknown_03005AF0;
extern PlayerSpriteInfo gPlayerLimbsPSI;
extern PlayerSpriteInfo gPlayerBodyPSI;
// TODO: Better name.
// This is used for an apparent around the value Cream uses for flying duration
@@ -180,8 +180,21 @@ typedef struct Player_ {
/* 0x8C */ struct Task *spriteTask;
/* 0x90 */ PlayerSpriteInfo *spriteInfoBody; // for character sprites
/* 0x94 */ PlayerSpriteInfo *spriteInfoLimbs; // SpriteInfo for Tails' tails / Cream's ears, when rolling
#if PORTABLE
// NOTE: There's a copy in player.c's 'InitializePlayer' that
// copies via a (u32 *) to unk99.
//
// Since it is offset originally, platforms only writing words
// aligned (or crash when trying to write to an odd pointer) will
// not have the memory initialized properly.
//
// Ironically this is a non-crashing bug on GBA as well.
/* 0x99 */ s8 unk99[16];
/* 0x98 */ u8 unk98; // Multiplayer var. TODO: check sign!
#else
/* 0x98 */ u8 unk98; // Multiplayer var. TODO: check sign!
/* 0x99 */ s8 unk99[16];
#endif
/* 0x9A */ u8 fillerA9[0x3];
// Cream's framecounter for flying
+6
View File
@@ -117,6 +117,12 @@ typedef struct SaveGame {
extern struct SaveGame *gLoadedSaveGame;
#endif
#if (GAME == GAME_SA1)
#define LOADED_SAVE (&gLoadedSaveGame)
#elif (GAME == GAME_SA2)
#define LOADED_SAVE (gLoadedSaveGame)
#endif
#define MULTIPLAYER_RESULT_WIN 0
#define MULTIPLAYER_RESULT_LOSS 1
#define MULTIPLAYER_RESULT_DRAW 2
+6
View File
@@ -30,6 +30,12 @@ typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
#if (GAME == GAME_SA1)
typedef u8 MetatileIndexType;
#else
typedef u16 MetatileIndexType;
#endif
// If the DISPLAY_HEIGHT was >255, scanline effects would break,
// so we have to make this variable bigger.
// (u16 should be plenty for screen coordinates, right?)
+4 -4
View File
@@ -221,11 +221,11 @@ void CreateEggSaucer(void)
m4aSongNumStart(SE_253);
gUnknown_03005AF0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AF0.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayerBodyPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerBodyPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gUnknown_03005AA0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AA0.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayerLimbsPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerLimbsPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gActiveBossTask = TaskCreate(Task_EggSaucerIntro, sizeof(EggSaucer), 0x4000, 0, TaskDestructor_EggSaucerMain);
boss = TASK_DATA(gActiveBossTask);
+4 -4
View File
@@ -183,11 +183,11 @@ void CreateEggGoRound(void)
sub_8039ED4();
gPseudoRandom = gStageTime;
gUnknown_03005AF0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AF0.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayerBodyPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerBodyPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gUnknown_03005AA0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AA0.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayerLimbsPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerLimbsPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayer.stoodObj = NULL;
gPlayer.moveState &= ~MOVESTATE_STOOD_ON_OBJ;
+2 -2
View File
@@ -255,8 +255,8 @@ void CreateEggFrog(void)
gPlayer.moveState |= MOVESTATE_IGNORE_INPUT;
sub_8039ED4();
gPseudoRandom = gStageTime;
gUnknown_03005AF0.s.frameFlags &= ~0x3000;
gUnknown_03005AF0.s.frameFlags |= 0x1000;
gPlayerBodyPSI.s.frameFlags &= ~0x3000;
gPlayerBodyPSI.s.frameFlags |= 0x1000;
gActiveBossTask = TaskCreate(Task_EggFrogMain, sizeof(EggFrog), 0x4000, 0, TaskDestructor_EggFrogMain);
boss = TASK_DATA(gActiveBossTask);
+8 -8
View File
@@ -733,10 +733,10 @@ void CreateSuperEggRoboZ(void)
gPlayer.moveState |= MOVESTATE_IGNORE_INPUT;
sub_8039ED4();
gPseudoRandom = gStageTime;
gUnknown_03005AF0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AF0.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gUnknown_03005AA0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AA0.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayerBodyPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerBodyPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayerLimbsPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerLimbsPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
t = TaskCreate(Task_SuperEggRoboZMain, sizeof(SuperEggRoboZ), 0x4000, 0, TaskDestructor_SuperEggRoboZMain);
gActiveBossTask = t;
@@ -892,10 +892,10 @@ static void Task_804A9D8(void)
boss->unkB = 0;
gPlayer.moveState &= ~(MOVESTATE_IGNORE_INPUT);
gUnknown_03005AF0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AF0.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gUnknown_03005AA0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AA0.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayerBodyPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerBodyPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayerLimbsPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerLimbsPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gCurTask->main = Task_804AB24;
}
}
+1 -1
View File
@@ -310,7 +310,7 @@ static void CreateKikiProjectilePiece(s16 x, s16 y)
static void Task_ProjPieceMain(void)
{
Sprite *s2 = &gUnknown_03005AF0.s;
Sprite *s2 = &gPlayerBodyPSI.s;
Kiki_Proj *proj = TASK_DATA(gCurTask);
Sprite *s = &proj->s;
s16 x, y;
+2 -2
View File
@@ -284,8 +284,8 @@ NONMATCH("asm/non_matching/game/interactables_2/egg_utopia/sub_807E66C.inc", boo
playerX = I(gPlayer.qWorldX) - gCamera.x;
playerY = I(gPlayer.qWorldY) - gCamera.y;
// gUnknown_03005AF0.s.hitboxes[0] s-<hitboxes[0]
if (HB_COLLISION(x, y, s2->hitboxes[0], playerX, playerY, gUnknown_03005AF0.s.hitboxes[0])) {
// gPlayerBodyPSI.s.hitboxes[0] s-<hitboxes[0]
if (HB_COLLISION(x, y, s2->hitboxes[0], playerX, playerY, gPlayerBodyPSI.s.hitboxes[0])) {
return 1;
}
@@ -89,9 +89,9 @@ static void sub_80726E8(Sprite_WindUpStick *windUpStick)
gPlayer.spriteOffsetY = 14;
Player_SetMovestate_IsInScriptedSequence();
gPlayer.moveState |= MOVESTATE_IA_OVERRIDE;
windUpStick->unk12 = (gUnknown_03005AF0.s.frameFlags & SPRITE_FLAG_MASK_PRIORITY) >> SPRITE_FLAG_SHIFT_PRIORITY;
gUnknown_03005AF0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AF0.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
windUpStick->unk12 = (gPlayerBodyPSI.s.frameFlags & SPRITE_FLAG_MASK_PRIORITY) >> SPRITE_FLAG_SHIFT_PRIORITY;
gPlayerBodyPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerBodyPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, 1);
gPlayer.qWorldY = Q(windUpStick->unk4 + 3);
switch (windUpStick->unk10) {
@@ -137,8 +137,8 @@ static void sub_80727F4(Sprite_WindUpStick *windUpStick)
Player_ClearMovestate_IsInScriptedSequence();
gPlayer.moveState &= ~MOVESTATE_IA_OVERRIDE;
gUnknown_03005AF0.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gUnknown_03005AF0.s.frameFlags |= SPRITE_FLAG(PRIORITY, windUpStick->unk12);
gPlayerBodyPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_PRIORITY;
gPlayerBodyPSI.s.frameFlags |= SPRITE_FLAG(PRIORITY, windUpStick->unk12);
switch (windUpStick->unk10) {
case 1:
@@ -98,10 +98,10 @@ void sub_80803FC(Sprite_MultiplayerTeleport *sprite)
ringBonus += gRingCount;
gRingCount = ringBonus;
if ((gCurrentLevel != LEVEL_INDEX(ZONE_FINAL, ACT_TRUE_AREA_53)) && (Div(gRingCount, 100) != Div(prevRingCount, 100))
if (!IS_EXTRA_STAGE(gCurrentLevel) && (Div(gRingCount, 100) != Div(prevRingCount, 100))
&& (gGameMode == GAME_MODE_SINGLE_PLAYER)) {
u32 lives = gNumLives + 1;
SET_LIVES_B(lives);
LIVES_BOUND_CHECK_B(lives);
gMusicManagerState.unk3 = 0x10;
}
@@ -71,7 +71,7 @@ void Task_CollectRingEffect(void)
s->x -= gCamera.x;
s->y -= gCamera.y;
if (UpdateSpriteAnimation(s) == 0) {
if (UpdateSpriteAnimation(s) == ACMD_RESULT__ENDED) {
DisplaySprite(s);
gActiveCollectRingEffectCount--;
+94 -21
View File
@@ -1,3 +1,5 @@
#include <string.h> // memcpy
#include "global.h"
#include "core.h"
#include "malloc_vram.h"
@@ -9,12 +11,23 @@
#include "game/sa1_sa2_shared/demo_manager.h"
#include "game/sa1_sa2_shared/player.h"
// TODO: add headers for these into sakit
// TODO: add headers for these into sa1_sa2_shared
// instead of including from the main game
#include "game/save.h"
#include "game/title_screen.h"
#include "constants/animations.h"
#include "constants/anim_sizes.h"
#if (GAME == GAME_SA1)
#define DEMO_SPRITE_PRIO 1
#define DEMO_OAM_ORDER 15
#define DEMO_PLAYBACK_TIME ZONE_TIME_TO_INT(0, 30)
#elif (GAME == GAME_SA2)
#define DEMO_SPRITE_PRIO 0
#define DEMO_OAM_ORDER 1
#define DEMO_PLAYBACK_TIME ZONE_TIME_TO_INT(0, 24.5)
#endif
typedef struct {
/* 0x00 */ Sprite textPressStart;
@@ -38,16 +51,26 @@ void Task_DemoManagerMusicFadeout(void);
void CreateDemoManager(void)
{
u8 blendCtrl = gBldRegs.bldCnt & 0xC0;
s8 lang = gLoadedSaveGame->language;
struct Task *t = TaskCreate(Task_DemoManagerMain, sizeof(DemoManager), 1, 0, TaskDestructor_DemoManagerMain);
DemoManager *dm = TASK_DATA(t);
u8 blendCtrl;
s8 lang;
struct Task *t;
DemoManager *dm;
Sprite *s;
#if (GAME == GAME_SA1)
const AnimId arr[2];
memcpy(&arr, gPressStartTiles, sizeof(arr));
#endif
blendCtrl = gBldRegs.bldCnt & 0xC0;
#if (GAME == GAME_SA2)
lang = LOADED_SAVE->language;
#endif
t = TaskCreate(Task_DemoManagerMain, sizeof(DemoManager), 1, 0, TaskDestructor_DemoManagerMain);
dm = TASK_DATA(t);
dm->fadeBlendFactor = 0;
dm->tFadeout = 0;
dm->playerPressedStart = FALSE;
dm->timeLimitDisabled = gLoadedSaveGame->timeLimitDisabled;
dm->timeLimitDisabled = LOADED_SAVE->timeLimitDisabled;
gStageFlags |= STAGE_FLAG__DEMO_RUNNING;
@@ -55,21 +78,28 @@ void CreateDemoManager(void)
s->x = (DISPLAY_WIDTH / 2);
s->y = (DISPLAY_HEIGHT / 2) + 33;
#if (GAME == GAME_SA1)
s->graphics.dest = ALLOC_TILES(SA1_ANIM_PRESS_START_MSG_JP);
s->graphics.size = 0;
s->graphics.anim = arr[LOADED_SAVE->uiLanguage];
s->variant = 0;
#elif (GAME == GAME_SA2)
s->graphics.dest = VramMalloc(gPressStartTiles[lang].numTiles);
s->graphics.size = 0;
s->graphics.anim = gPressStartTiles[lang].anim;
s->variant = gPressStartTiles[lang].variant;
#endif
s->animCursor = 0;
s->prevVariant = -1;
s->qAnimDelay = 0;
s->animSpeed = 0x10;
s->animSpeed = SPRITE_ANIM_SPEED(1.0);
s->palId = 0;
s->oamFlags = SPRITE_OAM_ORDER(1);
s->frameFlags = 0;
s->oamFlags = SPRITE_OAM_ORDER(DEMO_OAM_ORDER);
s->frameFlags = SPRITE_FLAG(PRIORITY, DEMO_SPRITE_PRIO);
if (blendCtrl != BLDCNT_EFFECT_BLEND) {
s->frameFlags = SPRITE_FLAG(OBJ_MODE, ST_OAM_OBJ_BLEND);
s->frameFlags |= SPRITE_FLAG(OBJ_MODE, ST_OAM_OBJ_BLEND);
}
UpdateSpriteAnimation(s);
@@ -77,21 +107,28 @@ void CreateDemoManager(void)
s->x = (DISPLAY_WIDTH / 2);
s->y = (DISPLAY_HEIGHT / 2);
s->graphics.dest = VramMalloc(28);
#if (GAME == GAME_SA1)
s->graphics.dest = ALLOC_TILES(SA1_ANIM_DEMO_PLAY);
s->graphics.size = 0;
s->graphics.anim = SA2_ANIM_DEMO_PLAY;
s->graphics.anim = SA1_ANIM_DEMO_PLAY;
s->variant = 0;
#elif (GAME == GAME_SA2)
s->graphics.dest = ALLOC_TILES(ANIM_DEMO_PLAY);
s->graphics.size = 0;
s->graphics.anim = ANIM_DEMO_PLAY;
s->variant = 0;
#endif
s->animCursor = 0;
s->prevVariant = -1;
s->qAnimDelay = 0;
s->animSpeed = 0x10;
s->palId = 0;
s->oamFlags = SPRITE_OAM_ORDER(1);
s->frameFlags = 0;
s->oamFlags = SPRITE_OAM_ORDER(DEMO_OAM_ORDER);
s->frameFlags = SPRITE_FLAG(PRIORITY, DEMO_SPRITE_PRIO);
if (blendCtrl != BLDCNT_EFFECT_BLEND) {
s->frameFlags = SPRITE_FLAG(OBJ_MODE, ST_OAM_OBJ_BLEND);
s->frameFlags |= SPRITE_FLAG(OBJ_MODE, ST_OAM_OBJ_BLEND);
}
UpdateSpriteAnimation(s);
}
@@ -114,8 +151,15 @@ void Task_DemoManagerMain(void)
gBldRegs.bldY = 0;
gMusicManagerState.unk0 = 0xFF;
#if (GAME == GAME_SA1)
m4aMPlayFadeOut(&gMPlayInfo_BGM, 4);
m4aMPlayFadeOut(&gMPlayInfo_SE1, 4);
m4aMPlayFadeOut(&gMPlayInfo_SE2, 4);
m4aMPlayFadeOut(&gMPlayInfo_SE3, 4);
#elif (GAME == GAME_SA2)
CreateMusicFadeoutTask(64);
} else if (gCheckpointTime > (u32)ZONE_TIME_TO_INT(0, 24.5)) {
#endif
} else if (gCheckpointTime > (u32)DEMO_PLAYBACK_TIME) {
dm->playerPressedStart = FALSE;
gCurTask->main = Task_DemoManagerFadeout;
@@ -124,20 +168,37 @@ void Task_DemoManagerMain(void)
gBldRegs.bldY = 0;
gMusicManagerState.unk0 = 0xFF;
#if (GAME == GAME_SA1)
m4aMPlayFadeOut(&gMPlayInfo_BGM, 4);
m4aMPlayFadeOut(&gMPlayInfo_SE1, 4);
m4aMPlayFadeOut(&gMPlayInfo_SE2, 4);
m4aMPlayFadeOut(&gMPlayInfo_SE3, 4);
#elif (GAME == GAME_SA2)
CreateMusicFadeoutTask(64);
#endif
}
if (!(gStageFlags & STAGE_FLAG__100)) {
#if (GAME == GAME_SA2)
if (!(gStageFlags & STAGE_FLAG__100))
#endif
{
Sprite *s = &dm->textPressStart;
if (gStageTime & 0x20) {
#if (GAME == GAME_SA1)
if (gCheckpointTime & 0x20)
#elif (GAME == GAME_SA2)
if (gStageTime & 0x20)
#endif
{
if (gBldRegs.bldY != 0) {
s->frameFlags |= SPRITE_FLAG(OBJ_MODE, ST_OAM_OBJ_BLEND);
} else {
s->frameFlags &= ~SPRITE_FLAG_MASK_OBJ_MODE;
}
#if (GAME == GAME_SA2)
UpdateSpriteAnimation(s);
#endif
DisplaySprite(s);
}
@@ -156,23 +217,33 @@ void Task_DemoManagerEndFadeout(void)
DemoManager *dm = TASK_DATA(gCurTask);
dm->tFadeout++;
#if (GAME == GAME_SA2)
m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0);
m4aMPlayVolumeControl(&gMPlayInfo_SE1, 0xFFFF, 0);
m4aMPlayVolumeControl(&gMPlayInfo_SE2, 0xFFFF, 0);
m4aMPlayVolumeControl(&gMPlayInfo_SE3, 0xFFFF, 0);
#endif
if (dm->tFadeout >= 48) {
gLoadedSaveGame->timeLimitDisabled = dm->timeLimitDisabled;
LOADED_SAVE->timeLimitDisabled = dm->timeLimitDisabled;
TasksDestroyAll();
PAUSE_BACKGROUNDS_QUEUE();
gUnknown_03005390 = 0;
SA2_LABEL(gUnknown_03005390) = 0;
PAUSE_GRAPHICS_QUEUE();
#if (GAME == GAME_SA1)
if (!dm->playerPressedStart) {
CreateSegaLogo();
} else {
CreateTitleScreen(TITLESCREEN_PARAM__PLAY_MUSIC);
}
#elif (GAME == GAME_SA2)
if (!dm->playerPressedStart) {
CreateTitleScreen();
} else {
CreateTitleScreenAtPlayModeMenu();
}
#endif
}
}
@@ -198,6 +269,7 @@ void TaskDestructor_DemoManagerMain(struct Task *t)
gStageFlags &= ~STAGE_FLAG__DEMO_RUNNING;
}
#if (GAME == GAME_SA2)
void CreateMusicFadeoutTask(u16 factor)
{
struct Task *t = TaskCreate(Task_DemoManagerMusicFadeout, sizeof(DemoMusicFadeout), 0xFFFE, 0, NULL);
@@ -220,4 +292,5 @@ void Task_DemoManagerMusicFadeout(void)
if ((s16)mf->volume < 0) {
mf->volume = 0;
}
}
}
#endif
+1 -1
View File
@@ -39,7 +39,7 @@ static void Task_CreateDustCloud(void)
s->x -= gCamera.x;
s->y -= gCamera.y;
if (UpdateSpriteAnimation(s) == 0) {
if (UpdateSpriteAnimation(s) == ACMD_RESULT__ENDED) {
DisplaySprite(s);
TaskDestroy(gCurTask);
#ifdef BUG_FIX
+30 -25
View File
@@ -120,8 +120,13 @@ typedef struct Task *(*StagePreInitFunc)(void);
typedef void (*MapEntityInit)(MapEntity *, u16, u16, u8);
struct Range {
s32 xLow, yLow;
s32 xHigh, yHigh;
CamCoord xLow, yLow;
CamCoord xHigh, yHigh;
};
struct Ranges {
struct Range a;
struct Range b;
};
void Task_8008DCC(void);
@@ -612,7 +617,7 @@ void SpawnMapEntities()
void Task_8008DCC(void)
{
#ifndef NON_MATCHING
struct Range *newRange2Ptr;
struct Range *newrange2Ptr;
#endif
if (!(gStageFlags & 2)) {
u32 i;
@@ -630,7 +635,7 @@ void Task_8008DCC(void)
u32 *itemBoxPositions;
u32 *enemyPositions;
if (em->unk14 != 0) {
if (em->SA2_LABEL(unk14) != 0) {
SpawnMapEntities();
return;
}
@@ -692,7 +697,7 @@ void Task_8008DCC(void)
range1.xHigh = em->prevCamX - 128;
}
if (em->unk14 != 0) {
if (em->SA2_LABEL(unk14) != 0) {
SpawnMapEntities();
return;
}
@@ -795,7 +800,7 @@ void Task_8008DCC(void)
// Hack to fix a stack mismatch, must be placed here
#ifndef NON_MATCHING
newRange2Ptr = &range2;
newrange2Ptr = &range2;
#endif
if (gCamera.x != em->prevCamX && range1.xLow != range1.xHigh && range1.yLow != range1.yHigh) {
@@ -810,8 +815,8 @@ void Task_8008DCC(void)
MapEntity *me = ((void *)interactables + (i - 8));
for (i = 0; (s8)me->x != -1; me++, i++) {
if ((s8)me->x >= -2) {
s32 x = TO_WORLD_POS(me->x, regionX);
s32 y = TO_WORLD_POS(me->y, regionY);
CamCoord x = TO_WORLD_POS(me->x, regionX);
CamCoord y = TO_WORLD_POS(me->y, regionY);
if (x >= range1.xLow && x <= range1.xHigh && y >= range1.yLow && y <= range1.yHigh) {
gSpriteInits_Interactables[me->index](me, regionX, regionY, i);
}
@@ -824,8 +829,8 @@ void Task_8008DCC(void)
MapEntity_Itembox *me = ((void *)itemBoxPositions + (i - 8));
for (i = 0; (s8)me->x != -1; me++, i++) {
if ((s8)me->x >= -2) {
s32 x = TO_WORLD_POS(me->x, regionX);
s32 y = TO_WORLD_POS(me->y, regionY);
CamCoord x = TO_WORLD_POS(me->x, regionX);
CamCoord y = TO_WORLD_POS(me->y, regionY);
if (x >= range1.xLow && x <= range1.xHigh && y >= range1.yLow && y <= range1.yHigh) {
CreateEntity_ItemBox((MapEntity *)me, regionX, regionY, i);
}
@@ -838,8 +843,8 @@ void Task_8008DCC(void)
MapEntity *me = ((void *)enemyPositions + (i - 8));
for (i = 0; (s8)me->x != -1; me++, i++) {
if ((s8)me->x >= -2) {
s32 x = TO_WORLD_POS(me->x, regionX);
s32 y = TO_WORLD_POS(me->y, regionY);
CamCoord x = TO_WORLD_POS(me->x, regionX);
CamCoord y = TO_WORLD_POS(me->y, regionY);
if (x >= range1.xLow && x <= range1.xHigh && y >= range1.yLow && y <= range1.yHigh) {
gSpriteInits_Enemies[me->index](me, regionX, regionY, i);
}
@@ -852,8 +857,8 @@ void Task_8008DCC(void)
MapEntity *me = ((void *)interactables + (i - 8));
for (i = 0; (s8)me->x != -1; me++, i++) {
if ((s8)me->x >= -2) {
s32 x = TO_WORLD_POS(me->x, regionX);
s32 y = TO_WORLD_POS(me->y, regionY);
CamCoord x = TO_WORLD_POS(me->x, regionX);
CamCoord y = TO_WORLD_POS(me->y, regionY);
if (x >= range1.xLow && x <= range1.xHigh && y >= range1.yLow && y <= range1.yHigh) {
gSpriteInits_InteractablesMultiplayer[me->index](me, regionX, regionY, i);
}
@@ -868,9 +873,9 @@ void Task_8008DCC(void)
}
#ifndef NON_MATCHING
if (((gCamera.y != em->prevCamY) && ((*newRange2Ptr).yLow != (*newRange2Ptr).yHigh)) && (range2.xLow != (*newRange2Ptr).xHigh)) {
regionY = I((*newRange2Ptr).yLow);
while (Q(regionY) < (*newRange2Ptr).yHigh && regionY < v_regionCount) {
if (((gCamera.y != em->prevCamY) && ((*newrange2Ptr).yLow != (*newrange2Ptr).yHigh)) && (range2.xLow != (*newrange2Ptr).xHigh)) {
regionY = I((*newrange2Ptr).yLow);
while (Q(regionY) < (*newrange2Ptr).yHigh && regionY < v_regionCount) {
#else
if (((gCamera.y != em->prevCamY) && (range2.yLow != range2.yHigh)) && (range2.xLow != range2.xHigh)) {
regionY = I(range2.yLow);
@@ -884,8 +889,8 @@ void Task_8008DCC(void)
MapEntity *me = ((void *)interactables + (i - 8));
for (i = 0; (s8)me->x != -1; me++, i++) {
if ((s8)me->x >= -2) {
s32 x = TO_WORLD_POS(me->x, regionX);
s32 y = TO_WORLD_POS(me->y, regionY);
CamCoord x = TO_WORLD_POS(me->x, regionX);
CamCoord y = TO_WORLD_POS(me->y, regionY);
if (x >= range2.xLow && x <= range2.xHigh && y >= range2.yLow && y <= range2.yHigh) {
gSpriteInits_Interactables[me->index](me, regionX, regionY, i);
}
@@ -898,8 +903,8 @@ void Task_8008DCC(void)
MapEntity_Itembox *me = ((void *)itemBoxPositions + (i - 8));
for (i = 0; (s8)me->x != -1; me++, i++) {
if ((s8)me->x >= -2) {
s32 x = TO_WORLD_POS(me->x, regionX);
s32 y = TO_WORLD_POS(me->y, regionY);
CamCoord x = TO_WORLD_POS(me->x, regionX);
CamCoord y = TO_WORLD_POS(me->y, regionY);
if (x >= range2.xLow && x <= range2.xHigh && y >= range2.yLow && y <= range2.yHigh) {
CreateEntity_ItemBox((MapEntity *)me, regionX, regionY, i);
}
@@ -912,8 +917,8 @@ void Task_8008DCC(void)
MapEntity *me = ((void *)enemyPositions + (i - 8));
for (i = 0; (s8)me->x != -1; me++, i++) {
if ((s8)me->x >= -2) {
s32 x = TO_WORLD_POS(me->x, regionX);
s32 y = TO_WORLD_POS(me->y, regionY);
CamCoord x = TO_WORLD_POS(me->x, regionX);
CamCoord y = TO_WORLD_POS(me->y, regionY);
if (x >= range2.xLow && x <= range2.xHigh && y >= range2.yLow && y <= range2.yHigh) {
gSpriteInits_Enemies[me->index](me, regionX, regionY, i);
}
@@ -926,8 +931,8 @@ void Task_8008DCC(void)
MapEntity *me = ((void *)interactables + (i - 8));
for (i = 0; (s8)me->x != -1; me++, i++) {
if ((s8)me->x >= -2) {
s32 x = TO_WORLD_POS(me->x, regionX);
s32 y = TO_WORLD_POS(me->y, regionY);
CamCoord x = TO_WORLD_POS(me->x, regionX);
CamCoord y = TO_WORLD_POS(me->y, regionY);
if (x >= range2.xLow && x <= range2.xHigh && y >= range2.yLow && y <= range2.yHigh) {
gSpriteInits_InteractablesMultiplayer[me->index](me, regionX, regionY, i);
}
+1 -1
View File
@@ -62,7 +62,7 @@ void Task_MagneticRing(void)
ringY = ring->s.y;
ringX = ring->s.x;
if (HB_TOUCHING_RING(I(gPlayer.qWorldX), I(gPlayer.qWorldY), ringX, ringY, gUnknown_03005AF0.s.hitboxes[0])) {
if (HB_TOUCHING_RING(I(gPlayer.qWorldX), I(gPlayer.qWorldY), ringX, ringY, gPlayerBodyPSI.s.hitboxes[0])) {
if (PLAYER_IS_ALIVE) {
INCREMENT_RINGS(1);
+71 -20
View File
@@ -1,14 +1,15 @@
#include "global.h"
#include "tilemap.h"
#include "game/stage/collision.h"
#include "game/stage/camera.h"
#include "game/stage/player.h"
#include "constants/zones.h"
static ALIGNED(8) u32 gUnknown_3000410[3];
static ALIGNED(8) u32 gUnknown_3000420[3];
s32 sub_801EF94(s32 p0, s32 p1, s32 layer);
s32 SA2_LABEL(sub_801EF94)(s32 p0, s32 p1, s32 layer);
#define POS__NOT_MOD(i) \
if (p3 > 0) { \
@@ -55,6 +56,47 @@ s32 sub_801EF94(s32 p0, s32 p1, s32 layer);
return (p0 % 8u) - ((i)*TILE_WIDTH); \
}
#if (GAME == GAME_SA1)
extern const Collision CollHeader_zone_1_act_1_fg;
extern const Collision CollHeader_zone_1_act_2_fg;
extern const Collision CollHeader_zone_2_act_1_fg;
extern const Collision CollHeader_zone_2_act_2_fg;
extern const Collision CollHeader_zone_3_act_1_fg;
extern const Collision CollHeader_zone_3_act_2_fg;
extern const Collision CollHeader_zone_4_act_1_fg;
extern const Collision CollHeader_zone_4_act_2_fg;
extern const Collision CollHeader_zone_5_act_1_fg;
extern const Collision CollHeader_zone_5_act_2_fg;
extern const Collision CollHeader_zone_6_act_1_fg;
extern const Collision CollHeader_zone_6_act_2_fg;
extern const Collision CollHeader_zone_7_act_1_fg;
extern const Collision CollHeader_zone_7_act_2_fg;
extern const Collision CollHeader_zone_chao_hunt_act_vs_zone_a_fg;
extern const Collision CollHeader_zone_chao_hunt_act_vs_zone_b_fg;
extern const Collision CollHeader_zone_chao_hunt_act_vs_zone_c_fg;
extern const Collision CollHeader_zone_chao_hunt_act_vs_zone_d_fg;
const Collision *const gCollisionTable[NUM_LEVEL_IDS] = {
&CollHeader_zone_1_act_1_fg,
&CollHeader_zone_1_act_2_fg,
&CollHeader_zone_2_act_1_fg,
&CollHeader_zone_2_act_2_fg,
&CollHeader_zone_3_act_1_fg,
&CollHeader_zone_3_act_2_fg,
&CollHeader_zone_4_act_1_fg,
&CollHeader_zone_4_act_2_fg,
&CollHeader_zone_5_act_1_fg,
&CollHeader_zone_5_act_2_fg,
&CollHeader_zone_6_act_1_fg,
&CollHeader_zone_6_act_2_fg,
&CollHeader_zone_7_act_1_fg,
&CollHeader_zone_7_act_2_fg,
&CollHeader_zone_chao_hunt_act_vs_zone_a_fg,
&CollHeader_zone_chao_hunt_act_vs_zone_b_fg,
&CollHeader_zone_chao_hunt_act_vs_zone_c_fg,
&CollHeader_zone_chao_hunt_act_vs_zone_d_fg,
};
#elif (GAME == GAME_SA2)
extern const Collision CollHeader_zone_1_act_1_fg;
extern const Collision CollHeader_zone_1_act_2_fg;
extern const Collision CollHeader_zone_1_act_boss_fg;
@@ -94,8 +136,9 @@ const Collision *const gCollisionTable[] = {
&CollHeader_zone_1_act_dummy_fg, &CollHeader_zone_final_act_xx_fg, &CollHeader_zone_final_act_ta53_fg,
&CollHeader_zone_final_act_unused_fg,
};
#endif
s32 sub_801E4E4(s32 p0, s32 p1, s32 p2, s32 p3, u8 *data, Func801F07C func)
s32 SA2_LABEL(sub_801E4E4)(s32 p0, s32 p1, s32 p2, s32 p3, u8 *data, Func801F07C func)
{
u8 dummy[4];
u8 *dummy_p;
@@ -422,7 +465,7 @@ s32 sub_801E6D4(s32 p0, s32 p1, s32 p2, s32 p3, u8 *data, Func801F07C func)
}
#endif
s32 sub_801EB44(s32 p0, s32 p1, s32 layer)
s32 SA2_LABEL(sub_801EB44)(s32 p0, s32 p1, s32 layer)
{
u32 r0;
s32 yPixel;
@@ -435,7 +478,7 @@ s32 sub_801EB44(s32 p0, s32 p1, s32 layer)
p0 = CLAMP_32(p0, 0, gRefCollision->pxWidth - 1);
p1 = CLAMP_32(p1, 0, gRefCollision->pxHeight - 1);
tile = sub_801EF94(p0, p1, layer & PLAYER_LAYER__MASK);
tile = SA2_LABEL(sub_801EF94)(p0, p1, layer & PLAYER_LAYER__MASK);
mtTileIndex = tile & TILE_MASK_INDEX;
yPixel = p1 % (unsigned)TILE_WIDTH;
@@ -482,7 +525,7 @@ s32 sub_801EB44(s32 p0, s32 p1, s32 layer)
return hv;
}
s32 sub_801EC3C(s32 p0, s32 p1, s32 layer)
s32 SA2_LABEL(sub_801EC3C)(s32 p0, s32 p1, s32 layer)
{
u32 r0;
s32 xPixel;
@@ -495,7 +538,7 @@ s32 sub_801EC3C(s32 p0, s32 p1, s32 layer)
p1 = CLAMP_32(p1, 0, gRefCollision->pxWidth - 1);
p0 = CLAMP_32(p0, 0, gRefCollision->pxHeight - 1);
tile = sub_801EF94(p1, p0, layer & PLAYER_LAYER__MASK);
tile = SA2_LABEL(sub_801EF94)(p1, p0, layer & PLAYER_LAYER__MASK);
mtTileIndex = tile & TILE_MASK_INDEX;
xPixel = p1 % (unsigned)TILE_WIDTH;
@@ -538,7 +581,7 @@ s32 sub_801EC3C(s32 p0, s32 p1, s32 layer)
return hv;
}
s32 sub_801ED24(s32 p0, s32 p1, s32 p2, u8 *p3)
s32 SA2_LABEL(sub_801ED24)(s32 p0, s32 p1, s32 p2, u8 *p3)
{
u32 r0;
s32 r3;
@@ -551,7 +594,7 @@ s32 sub_801ED24(s32 p0, s32 p1, s32 p2, u8 *p3)
p0 = CLAMP_32(p0, 0, gRefCollision->pxWidth - 1);
p1 = CLAMP_32(p1, 0, gRefCollision->pxHeight - 1);
res = sub_801EF94(p0, p1, p2 & 0x1);
res = SA2_LABEL(sub_801EF94)(p0, p1, p2 & 0x1);
mtTileIndex = res & 0x3FF;
r3 = p1 % 8u;
@@ -619,11 +662,19 @@ s32 sub_801ED24(s32 p0, s32 p1, s32 p2, u8 *p3)
// TODO: Fix this register mess!
// (100.00%) https://decomp.me/scratch/sJY4g
s32 sub_801EE64(s32 p0in, s32 p1in, s32 p2in, u8 *p3in)
s32 SA2_LABEL(sub_801EE64)(s32 p0in, s32 p1in, s32 p2in, u8 *p3in)
{
// NOTE: I'm surprised it is using UNsigned ints in SA2.
// TODO: Should we consider the SA2 type a bugfix in SA1?
#if (GAME == GAME_SA1)
typedef s32 r0r1_t;
#elif (GAME == GAME_SA2)
typedef u32 r0r1_t;
#endif
#ifndef NON_MATCHING
register u32 r0 asm("r0");
register u32 r1 asm("r1");
register r0r1_t r0 asm("r0");
register r0r1_t r1 asm("r1");
register s32 r3 asm("r3");
register s32 p0 asm("r4") = p0in;
register s32 p1 asm("r5") = p1in;
@@ -634,8 +685,8 @@ s32 sub_801EE64(s32 p0in, s32 p1in, s32 p2in, u8 *p3in)
register u8 *p3 asm("sl") = p3in;
register s32 res asm("r4");
#else
u32 r0;
u32 r1;
r0r1_t r0;
r0r1_t r1;
s32 r3;
s32 p0 = p0in;
s32 p1 = p1in;
@@ -676,7 +727,7 @@ s32 sub_801EE64(s32 p0in, s32 p1in, s32 p2in, u8 *p3in)
sb = 1;
p0 = sub_801EF94(p1, p0, p2 & sb);
p0 = SA2_LABEL(sub_801EF94)(p1, p0, p2 & sb);
r7 = 0x3FF;
r7 &= p0;
@@ -757,7 +808,7 @@ s32 sub_801EE64(s32 p0in, s32 p1in, s32 p2in, u8 *p3in)
// TODO: This should return a u16, representing a tile inside a metatile
// TODO: Fix this register mess!
// (100.00%) https://decomp.me/scratch/nh7WN
s32 sub_801EF94(s32 p0, s32 p1, s32 layer)
s32 SA2_LABEL(sub_801EF94)(s32 p0, s32 p1, s32 layer)
{
s32 r0;
#ifndef NON_MATCHING
@@ -817,7 +868,7 @@ s32 sub_801EF94(s32 p0, s32 p1, s32 layer)
}
coll = gRefCollision;
mtIndex = ((u16 *)coll->map[layer])[(r3 * coll->levelX) + r8];
mtIndex = (coll->map[layer])[(r3 * coll->levelX) + r8];
// ((r5 << 3) + (r5 << 2)) == r5 * TILES_PER_METATILE_AXIS
r1 = ((r5 << 3) + (r5 << 2) + r7);
@@ -838,13 +889,13 @@ s32 sub_801EF94(s32 p0, s32 p1, s32 layer)
return result;
}
void sub_801F044(void)
void SA2_LABEL(sub_801F044)(void)
{
DmaFill32(3, 0, &gUnknown_3000410, sizeof(gUnknown_3000410));
DmaFill32(3, 0, &gUnknown_3000420, sizeof(gUnknown_3000420));
}
s32 sub_801F07C(s32 p0, s32 p1, s32 p2, s32 p3, u8 *data, Func801F07C func)
s32 SA2_LABEL(sub_801F07C)(s32 p0, s32 p1, s32 p2, s32 p3, u8 *data, Func801F07C func)
{
u8 dummy[4];
u8 *dummy_p;
@@ -890,7 +941,7 @@ s32 sub_801F07C(s32 p0, s32 p1, s32 p2, s32 p3, u8 *data, Func801F07C func)
return result;
}
s32 sub_801F100(s32 p0, s32 p1, s32 p2, s32 p3, Func801F100 func)
s32 SA2_LABEL(sub_801F100)(s32 p0, s32 p1, s32 p2, s32 p3, Func801F100 func)
{
s32 result;
s32 funcRes = func(p0, p1, p2);
+2 -2
View File
@@ -621,7 +621,7 @@ static void Task_IntroControllerMain(void)
}
introController->counter = frameCounter;
gUnknown_03005AF0.s.frameFlags &= ~(SPRITE_FLAG_MASK_OBJ_MODE);
gPlayerBodyPSI.s.frameFlags &= ~(SPRITE_FLAG_MASK_OBJ_MODE);
if (frameCounter < 150) {
gPlayer.moveState |= MOVESTATE_100000;
@@ -692,7 +692,7 @@ static void Task_IntroControllerMain(void)
if (IS_MULTI_PLAYER) {
sub_8018818();
} else {
gUnknown_03005AF0.s.frameFlags &= ~SPRITE_FLAG_MASK_18;
gPlayerBodyPSI.s.frameFlags &= ~SPRITE_FLAG_MASK_18;
}
CreateStageUI();
TaskDestroy(gCurTask);
+60 -76
View File
@@ -48,9 +48,9 @@ typedef struct {
Player ALIGNED(8) gPlayer = {};
// Poentially some extra space on player for this to be aligned 16 (should be 8)
PlayerSpriteInfo ALIGNED(16) gUnknown_03005AA0 = {};
PlayerSpriteInfo ALIGNED(16) gUnknown_03005AF0 = {};
// Potentially some extra space on player for this to be aligned 16 (should be 8)
PlayerSpriteInfo ALIGNED(16) gPlayerLimbsPSI = {};
PlayerSpriteInfo ALIGNED(16) gPlayerBodyPSI = {};
// sakit
extern void InitNewInputCounters(void);
@@ -530,19 +530,14 @@ static inline void Player_CameraShift_inline(Player *p)
void sub_80213C0(u32 UNUSED characterId, u32 UNUSED levelId, Player *player)
{
#ifndef NON_MATCHING
register Player *p asm("r5") = player;
#else
Player *p = player;
#endif
s32 playerID = p->playerID;
struct Task *t;
player_0_Task *gt;
t = TaskCreate(Task_PlayerMain, sizeof(player_0_Task), 0x3000, 0, TaskDestructor_Player);
p->spriteTask = t;
gt = TASK_DATA(t);
Player *p = player;
s32 playerID = p->playerID;
p->spriteTask = TaskCreate(Task_PlayerMain, sizeof(player_0_Task), 0x3000, 0, TaskDestructor_Player);
gt = TASK_DATA(p->spriteTask);
gt->unk0 = playerID;
gt->unk4 = 0;
@@ -684,21 +679,12 @@ void SetStageSpawnPos(u32 character, u32 level, u32 playerID, Player *p)
p->unk98 = 0;
p->checkpointTime = 0;
p->spriteInfoBody = &gUnknown_03005AF0;
p->spriteInfoLimbs = &gUnknown_03005AA0;
p->spriteInfoBody = &gPlayerBodyPSI;
p->spriteInfoLimbs = &gPlayerLimbsPSI;
}
void InitializePlayer(Player *p)
{
#ifndef NON_MATCHING
register s8 *u99_r6 asm("r6");
register s8 *playerID asm("r4");
#else
s8 *u99_r6;
s8 *playerID;
#endif
s8 *character;
if ((gGameMode == GAME_MODE_MULTI_PLAYER_COLLECT_RINGS) && (((p->qWorldX & p->qWorldY) + 1) != 0)) {
p->qWorldX = Q(460);
} else {
@@ -722,12 +708,26 @@ void InitializePlayer(Player *p)
p->unk29 = 0;
p->unk28 = 0;
p->layer = PLAYER_LAYER__BACK;
#if (GAME == GAME_SA1)
p->maxSpeed = Q(4.5);
#elif (GAME == GAME_SA2)
p->maxSpeed = Q(9.0);
p->topSpeed = Q(6.0);
p->acceleration = 8;
p->deceleration = 64;
#endif
#if (GAME == GAME_SA1)
p->acceleration = Q(8. / 256.);
p->deceleration = Q(96. / 256.);
#elif (GAME == GAME_SA2)
p->acceleration = Q(8. / 256.);
p->deceleration = Q(64. / 256.);
#endif
p->charState = CHARSTATE_IDLE;
#if (GAME == GAME_SA1)
p->prevCharState = 0;
#elif (GAME == GAME_SA2)
p->prevCharState = CHARSTATE_INVALID;
#endif
p->anim = -1;
p->variant = -1;
p->timerInvulnerability = 0;
@@ -736,19 +736,21 @@ void InitializePlayer(Player *p)
p->confusionTimer = 0;
p->stoodObj = NULL;
p->itemEffect = PLAYER_ITEM_EFFECT__NONE;
p->unk2A = 0;
p->unk72 = ZONE_TIME_TO_INT(0, 6);
p->unk7E = 0;
p->unk7C = 0;
p->unk82 = 0x100;
p->unk80 = 0x100;
p->SA2_LABEL(unk2A) = 0;
p->SA2_LABEL(unk72) = ZONE_TIME_TO_INT(0, 6);
p->SA2_LABEL(unk7E) = 0;
p->SA2_LABEL(unk7C) = 0;
p->SA2_LABEL(unk82) = Q(1);
p->SA2_LABEL(unk80) = Q(1);
p->defeatScoreIndex = 0;
p->unk61 = 0;
p->unk62 = 0;
p->unk63 = 0;
p->SA2_LABEL(unk61) = 0;
p->SA2_LABEL(unk62) = 0;
p->SA2_LABEL(unk63) = 0;
p->secondsUntilDrown = 30;
p->framesUntilDrownCountDecrement = 60;
p->unk88 = 10;
p->SA2_LABEL(unk88) = 10;
#if (GAME == GAME_SA2)
p->transition = 0;
p->unk6E = 0;
p->prevTransition = 0;
@@ -762,48 +764,28 @@ void InitializePlayer(Player *p)
sub_8015750();
sub_801561C();
Player_HandleBoostThreshold(p);
#ifndef NON_MATCHING
{
// Should be this but can't get it to match (even though it's functionally correct)
// so we resort back to asm
//
// u32 *u99 = (void *)p->unk99;
// s32 i = 4;
// u99_r6 = (void *)u99;
// playerID = &p->playerID;
// character = &p->character;
// while (i-- != 0) {
// *u99++ = 0;
// }
register u32 *u99 asm("r1") = (void *)p->unk99;
register s32 i asm("r2") = 3;
u99_r6 = (void *)u99;
playerID = &p->playerID;
character = &p->character;
asm("movs r3, #0\n"
"loop:\n"
"stm r1!, {r3}\n"
"add r0, r2, #0\n"
"sub r2, #1\n"
"cmp r0, #0\n"
"bne loop\n"
:
: "r"(u99), "r"(i));
}
#else
u99_r6 = p->unk99;
playerID = &p->playerID;
character = &p->character;
memset(p->unk99, 0, sizeof(p->unk99));
#endif
*u99_r6 = 0x7F;
{
u32 *ptr = (u32 *)(&p->SA2_LABEL(unk99)[0]);
s32 i = 3;
#if (GAME == GAME_SA2) && !defined(NON_MATCHING)
register u8 *u99_r6 asm("r6") = (void *)ptr;
#endif
do {
// @BUG: agbcc compiles this to an stmia instruction, which writes aligned words,
// so the written bytes are off by one, because SA2_LABEL(unk99) isn't word-aligned!
// >> writes unk98 - unk99[14]
*ptr++ = 0;
} while (i-- != 0);
#if (GAME == GAME_SA2) && !defined(NON_MATCHING)
*u99_r6 = 0x7F;
#else
p->SA2_LABEL(unk99)[0] = 0x7F;
#endif
}
if ((*playerID == 0) && IS_SINGLE_PLAYER) {
if ((p->playerID == 0) && IS_SINGLE_PLAYER) {
if (gCourseTime >= MAX_COURSE_TIME) {
gCheckpointTime = 0;
gCourseTime = 0;
@@ -814,18 +796,20 @@ void InitializePlayer(Player *p)
}
}
switch (*character) {
switch (p->character) {
case CHARACTER_SONIC: {
p->w.sf.flags = 0;
p->w.sf.unkAE = 0;
p->w.sf.unkB0 = 0;
} break;
#if (GAME == GAME_SA2)
case CHARACTER_CREAM: {
p->w.cf.unkAE = 0;
p->w.cf.flyingDuration = 0;
p->w.cf.unkB0 = 0;
} break;
#endif
case CHARACTER_TAILS: {
p->w.tf.flags = 0;
+204 -51
View File
@@ -17,8 +17,19 @@
#include "constants/animations.h"
#include "constants/songs.h"
#if (GAME == GAME_SA1)
#define MAX_SCATTERING_RINGS_COUNT_SP 48
#define MAX_SCATTERING_RINGS_COUNT_MP 32
#elif (GAME == GAME_SA2)
#define MAX_SCATTERING_RINGS_COUNT_SP 32
#define MAX_SCATTERING_RINGS_COUNT_MP 16
#endif
#if (GAME == GAME_SA1)
#define UNK10_CONDITION 1
#elif (GAME == GAME_SA2)
#define UNK10_CONDITION !(ring->unk10 & 0x7)
#endif
typedef struct {
/* 0x00 */ s32 x;
@@ -27,7 +38,9 @@ typedef struct {
/* 0x0A */ s16 velY;
/* 0x0C */ u16 unkC;
/* 0x0E */ s16 unkE;
#if (GAME == GAME_SA2)
/* 0x10 */ u16 unk10;
#endif
} ScatterRing; /* size: 0x14 */
typedef struct {
@@ -60,6 +73,15 @@ void InitPlayerHitRingsScatter(void)
void *dmaDest;
u32 size;
#if (GAME == GAME_SA1)
if (IS_MULTI_PLAYER) {
tgtTask = &gRingsScatterTask;
taskFn = Task_RingsScatter_MP_Multipak;
} else {
tgtTask = &gRingsScatterTask;
taskFn = Task_RingsScatter_Singleplayer;
}
#elif (GAME == GAME_SA2)
if (gGameMode != GAME_MODE_MULTI_PLAYER_COLLECT_RINGS) {
if (IS_SINGLE_PLAYER) {
tgtTask = &gRingsScatterTask;
@@ -72,6 +94,7 @@ void InitPlayerHitRingsScatter(void)
tgtTask = &gRingsScatterTask;
taskFn = Task_RingsScatter_MP_Singlepak;
}
#endif
size = sizeof(RingsScatter);
@@ -91,17 +114,36 @@ void InitPlayerHitRingsScatter(void)
s->graphics.dest = RESERVED_RING_TILES_VRAM;
s->oamFlags = SPRITE_OAM_ORDER(20);
s->graphics.size = 0;
#if (GAME == GAME_SA1)
s->graphics.anim = SA1_ANIM_RING;
#elif (GAME == GAME_SA2)
s->graphics.anim = SA2_ANIM_RING;
#endif
s->variant = 0;
s->animCursor = 0;
s->qAnimDelay = 0;
s->prevVariant = -1;
s->animSpeed = SPRITE_ANIM_SPEED(2.0);
s->palId = 0;
s->frameFlags = (SPRITE_FLAG(PRIORITY, 2) | SPRITE_FLAG_MASK_18 | SPRITE_FLAG_MASK_MOSAIC);
s->frameFlags = SPRITE_FLAG(PRIORITY, 2)
#if (GAME == GAME_SA2)
| SPRITE_FLAG_MASK_18 | SPRITE_FLAG_MASK_MOSAIC
#endif
;
rs->unk2B6 = 0;
#if (GAME == GAME_SA1)
if (!IS_EXTRA_STAGE(gCurrentLevel)) {
rs->unk2B4 = 0xE0;
rs->unk2B0 = 0x12;
} else {
rs->unk2B4 = 0xE0;
rs->unk2B0 = 7;
}
#else
rs->unk2B4 = 0x94;
rs->unk2B0 = 0x12;
#endif
dmaDest = rs->rings;
DmaFill16(3, 0, dmaDest, sizeof(rs->rings));
@@ -138,7 +180,11 @@ void InitScatteringRings(s32 x, s32 y, s32 numRings)
for (i = 0, ip = 0; i < (signed)ARRAY_COUNT(rs->rings); ring++, i++) {
if (ring->unkC == 0) {
#if (GAME == GAME_SA1)
ring->unkC = 256;
#elif (GAME == GAME_SA2)
ring->unkC = 180;
#endif
ring->unkE = p->layer;
ring->x = Q(x);
ring->y = Q(y);
@@ -156,10 +202,20 @@ void InitScatteringRings(s32 x, s32 y, s32 numRings)
}
r2 = r0;
#if (GAME == GAME_SA1)
{
s32 index = (r3 & 0xFF) * 4;
velX = SIN(index);
velX >>= r2;
velY = COS(index);
velY >>= r2;
}
#elif (GAME == GAME_SA2)
velX = SIN((r3 & 0xFF) * 4);
velX >>= r2;
velY = COS((r3 & 0xFF) * 4);
velY >>= r2;
#endif
velX -= (velX >> 2);
velY -= (velY >> 2);
@@ -178,6 +234,8 @@ void InitScatteringRings(s32 x, s32 y, s32 numRings)
r3 = -r3;
velX = -velX;
#if (GAME == GAME_SA2)
ring->unk10 = r2;
if (!(PseudoRandom32() & 0x10000)) {
@@ -185,6 +243,8 @@ void InitScatteringRings(s32 x, s32 y, s32 numRings)
}
ring->unk10 |= (ip & 0x3);
#endif
ip++;
if (ip >= numRings) {
@@ -194,21 +254,83 @@ void InitScatteringRings(s32 x, s32 y, s32 numRings)
}
}
#define USE_HITBOX_RECT 1
typedef struct {
/* 0x00 */ s8 left;
/* 0x01 */ s8 top;
/* 0x02 */ s8 right;
/* 0x03 */ s8 bottom;
} HitboxRect;
#if (GAME == GAME_SA1)
// TODO: Either not in SA2, or in a different place!
// Most of the structure is the same as InitScatteringRings,
// but it uses random values in more places.
// TODO: Use improved version of these globaly!
#define HB_ALT_LEFT(p, hb) (I((p)->qWorldX) + (hb)->left)
#define HB_ALT_WIDTH(hb) ((hb)->right - (hb)->left)
#define HB_ALT_RIGHT(p, hb) (I((p)->qWorldX) + HB_ALT_WIDTH(hb))
#define HB_ALT_TOP(p, hb) (I((p)->qWorldY) + (hb)->top)
#define HB_ALT_HEIGHT(hb) ((hb)->bottom - (hb)->top)
#define HB_ALT_BOTTOM(p, hb) (I((p)->qWorldY) + HB_ALT_HEIGHT(hb))
void sub_8040C1C(s32 x, s32 y, s32 numRings)
{
RingsScatter *rs = TASK_DATA(gRingsScatterTask);
ScatterRing *ring = &rs->rings[0];
Player *p = &gPlayer;
s32 i;
s32 ip;
s32 r2, r3, r7;
s32 velX = 0, velY = 0;
if (numRings == 0) {
return;
}
// Limit the displayed rings to 32
if (numRings > MAX_SCATTERING_RINGS_COUNT_SP) {
numRings = MAX_SCATTERING_RINGS_COUNT_SP;
}
// In Multiplayer, limit displayed rings to 16
if (IS_MULTI_PLAYER && (numRings > MAX_SCATTERING_RINGS_COUNT_MP)) {
numRings = MAX_SCATTERING_RINGS_COUNT_MP;
}
r7 = (((u32)PseudoRandom32() & 0xFF000) >> 12) | 0x10;
for (i = 0, ip = 0; i < (signed)ARRAY_COUNT(rs->rings); ring++, i++) {
if (ring->unkC == 0) {
ring->unkC = 256;
ring->unkE = p->layer;
ring->x = Q(x);
ring->y = Q(y);
r3 = (((u32)PseudoRandom32() & 0x1000) >> 12) + 5;
{
s32 r0;
{
s32 index = (r7 & 0xFF) * 4;
velX = SIN(index);
velX >>= r3;
velY = COS(index);
velY >>= r3;
}
velX -= (velX >> 2);
velY -= (velY >> 2);
}
if (GRAVITY_IS_INVERTED) {
velY = -velY;
}
ring->velX = +velX;
ring->velY = velY;
{
u32 rand = PseudoRandom32();
r7 += ((rand & 0x3F000) >> 12) + 16;
}
velX = -velX;
ip++;
if (ip >= numRings) {
return;
}
}
}
}
#endif
void RingsScatterSingleplayer_FlippedGravity(void)
{
@@ -236,25 +358,30 @@ void RingsScatterSingleplayer_FlippedGravity(void)
ringIntX = I(ring->x);
ringIntY = I(ring->y);
screenX = ringIntX - gCamera.x;
#ifndef NON_MATCHING
screenY = ({
s32 r0 = gCamera.y;
register s32 r2 asm("r2") = ringIntY;
asm("" ::"r"(r2));
r2 -= r0;
asm("" ::"r"(r2));
r2;
});
{
Camera *cam = &gCamera;
screenX = ringIntX - cam->x;
#if (GAME == GAME_SA2) && !(defined(NON_MATCHING))
screenY = ({
s32 r0 = cam->y;
register s32 r2 asm("r2") = ringIntY;
asm("" ::"r"(r2));
r2 -= r0;
asm("" ::"r"(r2));
r2;
});
#else
screenY = ringIntY - gCamera.y;
screenY = ringIntY - cam->y;
#endif
}
p = &gPlayer;
hb = &p->spriteInfoBody->s.hitboxes[0];
if (ring->unkC <= sp0C && (p->charState != SA2_CHAR_ANIM_20 || p->timerInvulnerability == 0) && IS_ALIVE(p)) {
Rect8 *rect = (Rect8 *)&hb->left;
if (RECT_TOUCHING_RING(I(p->qWorldX), I(p->qWorldY), ringIntX, ringIntY, rect)) {
CreateCollectRingEffect(ringIntX, ringIntY);
@@ -272,16 +399,16 @@ void RingsScatterSingleplayer_FlippedGravity(void)
}
}
if (ring->velY < 0 && !(ring->unk10 & 0x7)) {
s32 res = sub_801F100(ringIntY - (TILE_WIDTH * 2), ringIntX, ring->unkE, -8, sub_801EC3C);
if (ring->velY < 0 && UNK10_CONDITION) {
s32 res = SA2_LABEL(sub_801F100)(ringIntY - (TILE_WIDTH * 2), ringIntX, ring->unkE, -8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y -= Q_24_8(res);
ring->velY = (ring->velY >> 2) - ring->velY;
}
}
if (rs->unk2B6 & 0x1 && ring->velY > 0 && !(ring->unk10 & 0x7)) {
s32 res = sub_801F100(ringIntY, ringIntX, ring->unkE, 8, sub_801EC3C);
if (rs->unk2B6 & 0x1 && ring->velY > 0 && UNK10_CONDITION) {
s32 res = SA2_LABEL(sub_801F100)(ringIntY, ringIntX, ring->unkE, 8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y += Q_24_8(res);
ring->velY = (ring->velY >> 2) - ring->velY;
@@ -324,9 +451,11 @@ void RingsScatterSingleplayer_FlippedGravity(void)
}
{
#if (GAME == GAME_SA2)
u16 sprFlags = ring->unk10;
ring->unk10 &= ~0x3;
ring->unk10 |= (sprFlags + 1) & 0x3;
#endif
ring->unkC--;
}
}
@@ -343,7 +472,7 @@ void RingsScatterSingleplayer_NormalGravity(void)
s32 i; // sp14
s32 ringIntX, ringIntY;
s32 screenX, screenY;
s32 ip;
s32 bossWorldX; // Used in SA1 in the Extra Boss stage (apparently; non-matching right now)
Player *p;
Hitbox *hb;
@@ -355,22 +484,32 @@ void RingsScatterSingleplayer_NormalGravity(void)
continue;
}
#if (GAME == GAME_SA1)
ring->x += ring->velX;
ring->y += ring->velY;
#elif (GAME == GAME_SA2)
ring->x += ring->velX + gUnknown_030054FC;
ring->y += ring->velY + gUnknown_030054E0;
#endif
ringIntX = I(ring->x);
ip = ringIntX;
bossWorldX = ringIntX;
ringIntY = I(ring->y);
screenX = ringIntX - gCamera.x;
screenY = ringIntY - gCamera.y;
p = &gPlayer;
hb = &p->spriteInfoBody->s.hitboxes[0];
if ((ring->unkC <= sp0C) && ((p->charState != SA2_CHAR_ANIM_20) || (p->timerInvulnerability == 0)) && IS_ALIVE(p)) {
#if (GAME == GAME_SA1)
Rect8 *rect = &hb->b;
#else
Rect8 *rect = (Rect8 *)&hb->left;
#endif
if (RECT_TOUCHING_RING(I(p->qWorldX), I(p->qWorldY), ringIntX, ringIntY, rect)) {
CreateCollectRingEffect(ip, ringIntY);
CreateCollectRingEffect(bossWorldX, ringIntY);
INCREMENT_RINGS(1);
@@ -386,16 +525,18 @@ void RingsScatterSingleplayer_NormalGravity(void)
}
}
if (ring->velY > 0 && ((ring->unk10 & 0x7) == 0)) {
s32 res = sub_801F100(ringIntY, ringIntX, ring->unkE, +8, sub_801EC3C);
if (ring->velY > 0 && UNK10_CONDITION) {
s32 res = SA2_LABEL(sub_801F100)(ringIntY, ringIntX, ring->unkE, +8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y += Q_24_8(res);
ring->velY = (ring->velY >> 2) - ring->velY;
}
}
if (rs->unk2B6 & 0x1 && ring->velY < 0 && ((ring->unk10 & 0x7) == 0)) {
s32 res = sub_801F100((ringIntY - 16), ringIntX, ring->unkE, -8, sub_801EC3C);
if (rs->unk2B6 & 0x1 && ring->velY < 0 && UNK10_CONDITION) {
s32 res = SA2_LABEL(sub_801F100)((ringIntY - 16), ringIntX, ring->unkE, -8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y -= Q_24_8(res);
ring->velY = (ring->velY >> 2) - ring->velY;
@@ -438,14 +579,26 @@ void RingsScatterSingleplayer_NormalGravity(void)
}
{
#if (GAME == GAME_SA2)
u16 sprFlags = ring->unk10;
ring->unk10 &= ~0x3;
ring->unk10 |= (sprFlags + 1) & 0x3;
#endif
ring->unkC--;
}
}
}
#define USE_HITBOX_RECT 1
// TODO: Use improved version of these globaly!
#define HB_ALT_LEFT(p, hb) (I((p)->qWorldX) + (hb)->left)
#define HB_ALT_WIDTH(hb) ((hb)->right - (hb)->left)
#define HB_ALT_RIGHT(p, hb) (I((p)->qWorldX) + HB_ALT_WIDTH(hb))
#define HB_ALT_TOP(p, hb) (I((p)->qWorldY) + (hb)->top)
#define HB_ALT_HEIGHT(hb) ((hb)->bottom - (hb)->top)
#define HB_ALT_BOTTOM(p, hb) (I((p)->qWorldY) + HB_ALT_HEIGHT(hb))
// NOTE: VERY WRONG!!!
// A ton of code is missing here.
// (Basically a copy-paste of RingsScatterSingleplayer_FlippedGravity)
@@ -466,7 +619,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterMultipak_Flipped
s32 screenY; // sl
Player *p;
#if USE_HITBOX_RECT
HitboxRect *hb;
Rect8 *hb;
#else
Hitbox *hb;
#endif
@@ -489,7 +642,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterMultipak_Flipped
p = &gPlayer;
#if USE_HITBOX_RECT
hb = (HitboxRect *)&p->spriteInfoBody->s.hitboxes[0].left;
hb = (Rect8 *)&p->spriteInfoBody->s.hitboxes[0].left;
#else
hb = &p->spriteInfoBody->s.hitboxes[0];
#endif
@@ -514,7 +667,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterMultipak_Flipped
ring->unkC = 0;
} else {
if ((ring->velY < 0) && ((ring->unk10 & 0x7) == 0)) {
s32 res = sub_801F100((ringIntY - 16), ringIntX, ring->unkE, -8, sub_801EC3C);
s32 res = SA2_LABEL(sub_801F100)((ringIntY - 16), ringIntX, ring->unkE, -8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y -= Q(res);
ring->velY = (ring->velY >> 2) - ring->velY;
@@ -522,7 +675,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterMultipak_Flipped
}
if ((rs->unk2B6 & 0x1) && (ring->velY > 0) && ((ring->unk10 & 0x7) == 0)) {
s32 res = sub_801F100(ringIntY, ringIntX, ring->unkE, 8, sub_801EC3C);
s32 res = SA2_LABEL(sub_801F100)(ringIntY, ringIntX, ring->unkE, 8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y += Q(res);
ring->velY = (ring->velY >> 2) - ring->velY;
@@ -592,7 +745,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterMultipak_NormalG
s32 screenY; // sl
Player *p;
#if USE_HITBOX_RECT
HitboxRect *hb;
Rect8 *hb;
#else
Hitbox *hb;
#endif
@@ -615,7 +768,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterMultipak_NormalG
p = &gPlayer;
#if USE_HITBOX_RECT
hb = (HitboxRect *)&p->spriteInfoBody->s.hitboxes[0].left;
hb = (Rect8 *)&p->spriteInfoBody->s.hitboxes[0].left;
#else
hb = &p->spriteInfoBody->s.hitboxes[0];
#endif
@@ -641,7 +794,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterMultipak_NormalG
} else {
if ((ring->velY < 0) && ((ring->unk10 & 0x7) == 0)) {
s32 res = sub_801F100(ringIntY, ringIntX, ring->unkE, +8, sub_801EC3C);
s32 res = SA2_LABEL(sub_801F100)(ringIntY, ringIntX, ring->unkE, +8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y -= Q(res);
ring->velY = (ring->velY >> 2) - ring->velY;
@@ -649,7 +802,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterMultipak_NormalG
}
if ((rs->unk2B6 & 0x1) && (ring->velY > 0) && ((ring->unk10 & 0x7) == 0)) {
s32 res = sub_801F100((ringIntY - 16), ringIntX, ring->unkE, -8, sub_801EC3C);
s32 res = SA2_LABEL(sub_801F100)((ringIntY - 16), ringIntX, ring->unkE, -8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y += Q(res);
ring->velY = (ring->velY >> 2) - ring->velY;
@@ -721,7 +874,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterSinglepakMain.in
s32 screenY; // sl
Player *p;
#if USE_HITBOX_RECT
HitboxRect *hb;
Rect8 *hb;
#else
Hitbox *hb;
#endif
@@ -744,7 +897,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterSinglepakMain.in
p = &gPlayer;
#if USE_HITBOX_RECT
hb = (HitboxRect *)&p->spriteInfoBody->s.hitboxes[0].left;
hb = (Rect8 *)&p->spriteInfoBody->s.hitboxes[0].left;
#else
hb = &p->spriteInfoBody->s.hitboxes[0];
#endif
@@ -770,7 +923,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterSinglepakMain.in
} else {
if ((ring->velY < 0) && ((ring->unk10 & 0x7) == 0)) {
s32 res = sub_801F100(ringIntY, ringIntX, ring->unkE, +8, sub_801EC3C);
s32 res = SA2_LABEL(sub_801F100)(ringIntY, ringIntX, ring->unkE, +8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y -= Q(res);
ring->velY = (ring->velY >> 2) - ring->velY;
@@ -778,7 +931,7 @@ NONMATCH("asm/non_matching/game/stage/rings_scatter/RingsScatterSinglepakMain.in
}
if ((rs->unk2B6 & 0x1) && (ring->velY > 0) && ((ring->unk10 & 0x7) == 0)) {
s32 res = sub_801F100((ringIntY - 16), ringIntX, ring->unkE, -8, sub_801EC3C);
s32 res = SA2_LABEL(sub_801F100)((ringIntY - 16), ringIntX, ring->unkE, -8, SA2_LABEL(sub_801EC3C));
if (res <= 0) {
ring->y += Q(res);
ring->velY = (ring->velY >> 2) - ring->velY;