diff --git a/Makefile b/Makefile index 2628d52a..5ce37b40 100755 --- a/Makefile +++ b/Makefile @@ -16,14 +16,16 @@ ifeq ($(VERSION),us_1.0) DEFINES += VERSION_US_1_0=1 DEFINES += F3DDKR_GBI=1 endif -ifeq ($(NON_MATCHING),1) - DEFINES += NON_MATCHING=1 -endif ifeq ($(NON_EQUIVALENT),1) DEFINES += NON_EQUIVALENT=1 DEFINES += NON_MATCHING=1 NON_MATCHING = 1 endif +ifeq ($(NON_MATCHING),1) + DEFINES += NON_MATCHING=1 +else + DEFINES += ANTI_TAMPER=1 +endif # Whether to hide commands or not VERBOSE ?= 0 diff --git a/README.md b/README.md index 429f7467..2708980c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ As of January 26, 2024, this is our current score:     Decomp progress: 66.48% -    Documentation progress: 36.75% +    Documentation progress: 39.38% --- @@ -126,31 +126,31 @@ s32 is_drumstick_unlocked(void) { ``` -As of April 29, 2024, this is our current score: +As of May 3, 2024, this is our current score: ``` - ================================================================= - ADVENTURE ONE (ASM -> C Decompilation) - ------------- 66.48% Complete (69.07% NON_MATCHING) ------------- - # Decompiled functions: 1681 - # GLOBAL_ASM remaining: 164 - # NON_MATCHING functions: 15 - # NON_EQUIVALENT WIP functions: 55 - -------------------------- Game Status -------------------------- - Balloons: 31/47, Keys: 3/4, Trophies: 3/5 - T.T. Amulets: 3/4, Wizpig Amulets: 3/4 - ----------------------------------------------------------------- - We are racing in Windmill Plains. (Lap 3/3) - ================================================================= - ADVENTURE TWO (Cleanup & Documentation) - ------------------------ 36.75% Complete ------------------------ - # Documented functions: 863 - # Undocumented remaining: 705 - -------------------------- Game Status -------------------------- - Balloons: 18/47, Keys: 2/4, Trophies: 1/5 - T.T. Amulets: 2/4, Wizpig Amulets: 1/4 - ----------------------------------------------------------------- - We are collecting silver coins in Walrus Cove. (2/8 silver coins) - ================================================================= + ===================================================================== + ADVENTURE ONE (ASM -> C Decompilation) + --------------- 66.48% Complete (69.07% NON_MATCHING) --------------- + # Decompiled functions: 1681 + # GLOBAL_ASM remaining: 164 + # NON_MATCHING functions: 15 + # NON_EQUIVALENT WIP functions: 55 + ---------------------------- Game Status ---------------------------- + Balloons: 31/47, Keys: 3/4, Trophies: 3/5 + T.T. Amulets: 3/4, Wizpig Amulets: 3/4 + --------------------------------------------------------------------- + We are racing in Windmill Plains. (Lap 3/3) + ===================================================================== + ADVENTURE TWO (Cleanup & Documentation) + -------------------------- 39.38% Complete -------------------------- + # Documented functions: 942 + # Undocumented remaining: 626 + ---------------------------- Game Status ---------------------------- + Balloons: 19/47, Keys: 2/4, Trophies: 1/5 + T.T. Amulets: 2/4, Wizpig Amulets: 1/4 + --------------------------------------------------------------------- + We are collecting silver coins in Snowball Valley. (8/8 silver coins) + ===================================================================== ``` diff --git a/asm/assets/assets.s b/asm/assets/assets.s index 86c9db35..0047d653 100755 --- a/asm/assets/assets.s +++ b/asm/assets/assets.s @@ -8502,8 +8502,8 @@ glabel ASSET_MISC_RACER_HANDLING .incbin "./build/us_1.0/assets/misc/racer_stats/racer_handling_data.bin" glabel ASSET_MISC_RACER_UNUSED_11 .incbin "./build/us_1.0/assets/misc/racer_stats/racer_unused_11_data.bin" -glabel ASSET_MISC_12 -.incbin "./build/us_1.0/assets/misc/unlabeled/asset_misc_12.bin" +glabel ASSET_MISC_BALLOON_DATA +.incbin "./build/us_1.0/assets/misc/unlabeled/balloon_data.bin" glabel ASSET_MISC_13 .incbin "./build/us_1.0/assets/misc/unlabeled/asset_misc_13.bin" glabel ASSET_MISC_14 @@ -8526,8 +8526,8 @@ glabel ASSET_MISC_MAGNET_DATA .incbin "./build/us_1.0/assets/misc/unlabeled/magnet_data.bin" glabel ASSET_MISC_23 .incbin "./build/us_1.0/assets/misc/unlabeled/asset_misc_23.bin" -glabel ASSET_MISC_24 -.incbin "./build/us_1.0/assets/misc/unlabeled/asset_misc_24.bin" +glabel ASSET_MISC_GHOST_UNLOCK_TIMES +.incbin "./build/us_1.0/assets/misc/unlabeled/ghost_unlock_times.bin" glabel ASSET_MISC_25 .incbin "./build/us_1.0/assets/misc/unlabeled/asset_misc_25.bin" glabel ASSET_MISC_TRACKS_MENU_IDS @@ -8636,7 +8636,7 @@ glabel ASSET_MISC_TABLE .word (ASSET_MISC_RACER_WEIGHT - ASSET_MISC) / 4 .word (ASSET_MISC_RACER_HANDLING - ASSET_MISC) / 4 .word (ASSET_MISC_RACER_UNUSED_11 - ASSET_MISC) / 4 -.word (ASSET_MISC_12 - ASSET_MISC) / 4 +.word (ASSET_MISC_BALLOON_DATA - ASSET_MISC) / 4 .word (ASSET_MISC_13 - ASSET_MISC) / 4 .word (ASSET_MISC_14 - ASSET_MISC) / 4 .word (ASSET_MISC_15 - ASSET_MISC) / 4 @@ -8648,7 +8648,7 @@ glabel ASSET_MISC_TABLE .word (ASSET_MISC_SHIELD_DATA - ASSET_MISC) / 4 .word (ASSET_MISC_MAGNET_DATA - ASSET_MISC) / 4 .word (ASSET_MISC_23 - ASSET_MISC) / 4 -.word (ASSET_MISC_24 - ASSET_MISC) / 4 +.word (ASSET_MISC_GHOST_UNLOCK_TIMES - ASSET_MISC) / 4 .word (ASSET_MISC_25 - ASSET_MISC) / 4 .word (ASSET_MISC_TRACKS_MENU_IDS - ASSET_MISC) / 4 .word (ASSET_MISC_HUB_AREA_IDS - ASSET_MISC) / 4 diff --git a/asm/non_matchings/audio_spatial/func_80008174.s b/asm/non_matchings/audio_spatial/func_80008174.s index ce216a16..82376e6e 100644 --- a/asm/non_matchings/audio_spatial/func_80008174.s +++ b/asm/non_matchings/audio_spatial/func_80008174.s @@ -58,7 +58,7 @@ glabel func_80008174 /* 008E34 80008234 A0400012 */ sb $zero, 0x12($v0) /* 008E38 80008238 10800003 */ beqz $a0, .L80008248 /* 008E3C 8000823C 00000000 */ nop -/* 008E40 80008240 0C001223 */ jal func_8000488C +/* 008E40 80008240 0C001223 */ jal sound_stop /* 008E44 80008244 00000000 */ nop .L80008248: /* 008E48 80008248 968E0000 */ lhu $t6, ($s4) @@ -90,7 +90,7 @@ glabel func_80008174 /* 008EA8 800082A8 00000000 */ nop /* 008EAC 800082AC 14400005 */ bnez $v0, .L800082C4 /* 008EB0 800082B0 00000000 */ nop -/* 008EB4 800082B4 0C001223 */ jal func_8000488C +/* 008EB4 800082B4 0C001223 */ jal sound_stop /* 008EB8 800082B8 00000000 */ nop /* 008EBC 800082BC 10000006 */ b .L800082D8 /* 008EC0 800082C0 AE200178 */ sw $zero, 0x178($s1) @@ -180,7 +180,7 @@ glabel func_80008174 /* 008FF8 800083F8 14E8FFDF */ bne $a3, $t0, .L80008378 /* 008FFC 800083FC 24C600C0 */ addiu $a2, $a2, 0xc0 /* 009000 80008400 8FBF003C */ lw $ra, 0x3c($sp) -/* 009004 80008404 3C018012 */ lui $at, %hi(D_8011AC18) # $at, 0x8012 +/* 009004 80008404 3C018012 */ lui $at, %hi(gAudioLinesOff) # $at, 0x8012 /* 009008 80008408 C7B50018 */ lwc1 $f21, 0x18($sp) /* 00900C 8000840C C7B4001C */ lwc1 $f20, 0x1c($sp) /* 009010 80008410 8FB00020 */ lw $s0, 0x20($sp) @@ -190,7 +190,7 @@ glabel func_80008174 /* 009020 80008420 8FB40030 */ lw $s4, 0x30($sp) /* 009024 80008424 8FB50034 */ lw $s5, 0x34($sp) /* 009028 80008428 8FB60038 */ lw $s6, 0x38($sp) -/* 00902C 8000842C A020AC18 */ sb $zero, %lo(D_8011AC18)($at) +/* 00902C 8000842C A020AC18 */ sb $zero, %lo(gAudioLinesOff)($at) /* 009030 80008430 03E00008 */ jr $ra /* 009034 80008434 27BD0040 */ addiu $sp, $sp, 0x40 diff --git a/asm/non_matchings/audio_spatial/func_80008438.s b/asm/non_matchings/audio_spatial/func_80008438.s index 8951795e..8d61e91b 100644 --- a/asm/non_matchings/audio_spatial/func_80008438.s +++ b/asm/non_matchings/audio_spatial/func_80008438.s @@ -422,7 +422,7 @@ glabel func_80008438 /* 009650 80008A50 00000000 */ nop /* 009654 80008A54 10800008 */ beqz $a0, .L80008A78 /* 009658 80008A58 00000000 */ nop -/* 00965C 80008A5C 0C001223 */ jal func_8000488C +/* 00965C 80008A5C 0C001223 */ jal sound_stop /* 009660 80008A60 00000000 */ nop /* 009664 80008A64 92220011 */ lbu $v0, 0x11($s1) /* 009668 80008A68 00000000 */ nop @@ -774,7 +774,7 @@ glabel func_80008438 /* 009B6C 80008F6C 00000000 */ nop /* 009B70 80008F70 10800015 */ beqz $a0, .L80008FC8 /* 009B74 80008F74 8FAB0260 */ lw $t3, 0x260($sp) -/* 009B78 80008F78 0C001223 */ jal func_8000488C +/* 009B78 80008F78 0C001223 */ jal sound_stop /* 009B7C 80008F7C 00000000 */ nop /* 009B80 80008F80 10000011 */ b .L80008FC8 /* 009B84 80008F84 8FAB0260 */ lw $t3, 0x260($sp) @@ -804,11 +804,11 @@ glabel func_80008438 /* 009BD8 80008FD8 1581FEC7 */ bne $t4, $at, .L80008AF8 /* 009BDC 80008FDC 24420180 */ addiu $v0, $v0, 0x180 /* 009BE0 80008FE0 8FAE024C */ lw $t6, 0x24c($sp) -/* 009BE4 80008FE4 3C0D8012 */ lui $t5, %hi(D_8011AC18) # $t5, 0x8012 +/* 009BE4 80008FE4 3C0D8012 */ lui $t5, %hi(gAudioLinesOff) # $t5, 0x8012 /* 009BE8 80008FE8 29C1000B */ slti $at, $t6, 0xb /* 009BEC 80008FEC 14200015 */ bnez $at, .L80009044 /* 009BF0 80008FF0 00000000 */ nop -/* 009BF4 80008FF4 91ADAC18 */ lbu $t5, %lo(D_8011AC18)($t5) +/* 009BF4 80008FF4 91ADAC18 */ lbu $t5, %lo(gAudioLinesOff)($t5) /* 009BF8 80008FF8 00000000 */ nop /* 009BFC 80008FFC 15A00011 */ bnez $t5, .L80009044 /* 009C00 80009000 00000000 */ nop diff --git a/asm/non_matchings/audio_vehicle/func_80005254.s b/asm/non_matchings/audio_vehicle/func_80005254.s index afcaa057..6aad1b10 100644 --- a/asm/non_matchings/audio_vehicle/func_80005254.s +++ b/asm/non_matchings/audio_vehicle/func_80005254.s @@ -591,7 +591,7 @@ glabel func_80005254 /* 006684 80005A84 00000000 */ nop /* 006688 80005A88 1080000C */ beqz $a0, .L80005ABC /* 00668C 80005A8C 8FB900A4 */ lw $t9, 0xa4($sp) -/* 006690 80005A90 0C001223 */ jal func_8000488C +/* 006690 80005A90 0C001223 */ jal sound_stop /* 006694 80005A94 00000000 */ nop /* 006698 80005A98 8E380000 */ lw $t8, ($s1) /* 00669C 80005A9C 00000000 */ nop diff --git a/asm/non_matchings/audio_vehicle/func_800063EC.s b/asm/non_matchings/audio_vehicle/func_800063EC.s index 117e717b..d97f305b 100644 --- a/asm/non_matchings/audio_vehicle/func_800063EC.s +++ b/asm/non_matchings/audio_vehicle/func_800063EC.s @@ -480,7 +480,7 @@ glabel func_800063EC /* 0076A4 80006AA4 00000000 */ nop /* 0076A8 80006AA8 10800004 */ beqz $a0, .L80006ABC /* 0076AC 80006AAC 8FBF0014 */ lw $ra, 0x14($sp) -/* 0076B0 80006AB0 0C001223 */ jal func_8000488C +/* 0076B0 80006AB0 0C001223 */ jal sound_stop /* 0076B4 80006AB4 00000000 */ nop /* 0076B8 80006AB8 8FBF0014 */ lw $ra, 0x14($sp) .L80006ABC: diff --git a/asm/non_matchings/audio_vehicle/func_80006FC8.s b/asm/non_matchings/audio_vehicle/func_80006FC8.s index a6b36aa9..ed6ad3e6 100644 --- a/asm/non_matchings/audio_vehicle/func_80006FC8.s +++ b/asm/non_matchings/audio_vehicle/func_80006FC8.s @@ -338,7 +338,7 @@ glabel func_80006FC8 /* 00806C 8000746C 00000000 */ nop /* 008070 80007470 10800014 */ beqz $a0, .L800074C4 /* 008074 80007474 00000000 */ nop -/* 008078 80007478 0C001223 */ jal func_8000488C +/* 008078 80007478 0C001223 */ jal sound_stop /* 00807C 8000747C 00000000 */ nop /* 008080 80007480 8E8A0000 */ lw $t2, ($s4) /* 008084 80007484 00000000 */ nop @@ -351,7 +351,7 @@ glabel func_80006FC8 /* 00809C 8000749C 00000000 */ nop /* 0080A0 800074A0 10800008 */ beqz $a0, .L800074C4 /* 0080A4 800074A4 00000000 */ nop -/* 0080A8 800074A8 0C001223 */ jal func_8000488C +/* 0080A8 800074A8 0C001223 */ jal sound_stop /* 0080AC 800074AC 00000000 */ nop /* 0080B0 800074B0 8E8B0000 */ lw $t3, ($s4) /* 0080B4 800074B4 00000000 */ nop @@ -437,7 +437,7 @@ glabel func_80006FC8 /* 0081D8 800075D8 00000000 */ nop /* 0081DC 800075DC 10800047 */ beqz $a0, .L800076FC /* 0081E0 800075E0 00000000 */ nop -/* 0081E4 800075E4 0C001223 */ jal func_8000488C +/* 0081E4 800075E4 0C001223 */ jal sound_stop /* 0081E8 800075E8 00000000 */ nop /* 0081EC 800075EC 8E990000 */ lw $t9, ($s4) /* 0081F0 800075F0 10000042 */ b .L800076FC @@ -449,7 +449,7 @@ glabel func_80006FC8 /* 008204 80007604 00000000 */ nop /* 008208 80007608 16400008 */ bnez $s2, .L8000762C /* 00820C 8000760C 00000000 */ nop -/* 008210 80007610 0C001223 */ jal func_8000488C +/* 008210 80007610 0C001223 */ jal sound_stop /* 008214 80007614 00000000 */ nop /* 008218 80007618 8E880000 */ lw $t0, ($s4) /* 00821C 8000761C 00000000 */ nop @@ -892,7 +892,7 @@ glabel func_80006FC8 /* 008860 80007C60 29610008 */ slti $at, $t3, 8 /* 008864 80007C64 1020000A */ beqz $at, .L80007C90 /* 008868 80007C68 00000000 */ nop -/* 00886C 80007C6C 0C001223 */ jal func_8000488C +/* 00886C 80007C6C 0C001223 */ jal sound_stop /* 008870 80007C70 00000000 */ nop /* 008874 80007C74 8E6E0000 */ lw $t6, ($s3) /* 008878 80007C78 00000000 */ nop @@ -989,7 +989,7 @@ glabel func_80006FC8 /* 0089C8 80007DC8 00000000 */ nop /* 0089CC 80007DCC 1080000C */ beqz $a0, .L80007E00 /* 0089D0 80007DD0 240A003C */ li $t2, 60 -/* 0089D4 80007DD4 0C001223 */ jal func_8000488C +/* 0089D4 80007DD4 0C001223 */ jal sound_stop /* 0089D8 80007DD8 00000000 */ nop /* 0089DC 80007DDC 8E380000 */ lw $t8, ($s1) /* 0089E0 80007DE0 24190001 */ li $t9, 1 diff --git a/asm/non_matchings/game_ui/func_8009F034.s b/asm/non_matchings/game_ui/func_8009F034.s index bb2b977b..9bbfc15f 100644 --- a/asm/non_matchings/game_ui/func_8009F034.s +++ b/asm/non_matchings/game_ui/func_8009F034.s @@ -143,7 +143,7 @@ glabel func_8009F034 /* 09FDE4 8009F1E4 25F8FFFC */ addiu $t8, $t7, -4 /* 09FDE8 8009F1E8 AC780000 */ sw $t8, ($v1) .L8009F1EC: -/* 09FDEC 8009F1EC 0C006D90 */ jal get_time_trial_ghost +/* 09FDEC 8009F1EC 0C006D90 */ jal timetrial_ghost_staff /* 09FDF0 8009F1F0 00000000 */ nop /* 09FDF4 8009F1F4 14400004 */ bnez $v0, .L8009F208 /* 09FDF8 8009F1F8 240C0001 */ li $t4, 1 diff --git a/asm/non_matchings/game_ui/func_800A277C.s b/asm/non_matchings/game_ui/func_800A277C.s index d2e12a2e..8c538f89 100644 --- a/asm/non_matchings/game_ui/func_800A277C.s +++ b/asm/non_matchings/game_ui/func_800A277C.s @@ -730,11 +730,11 @@ glabel func_800A277C /* 0A3DE0 800A31E0 0C000741 */ jal sound_play /* 0A3DE4 800A31E4 24A56D40 */ addiu $a1, %lo(gHUDVoiceSoundMask) # addiu $a1, $a1, 0x6d40 .L800A31E8: -/* 0A3DE8 800A31E8 0C006CA2 */ jal func_8001B288 +/* 0A3DE8 800A31E8 0C006CA2 */ jal timetrial_valid_player_ghost /* 0A3DEC 800A31EC 00000000 */ nop /* 0A3DF0 800A31F0 1040004F */ beqz $v0, .L800A3330 /* 0A3DF4 800A31F4 8FAA00A0 */ lw $t2, 0xa0($sp) -/* 0A3DF8 800A31F8 0C006CB8 */ jal func_8001B2E0 +/* 0A3DF8 800A31F8 0C006CB8 */ jal timetrial_player_ghost /* 0A3DFC 800A31FC 00000000 */ nop /* 0A3E00 800A3200 1040004A */ beqz $v0, .L800A332C /* 0A3E04 800A3204 00408025 */ move $s0, $v0 diff --git a/asm/non_matchings/game_ui/func_800A6254.s b/asm/non_matchings/game_ui/func_800A6254.s index e2ded3e2..aae0b998 100644 --- a/asm/non_matchings/game_ui/func_800A6254.s +++ b/asm/non_matchings/game_ui/func_800A6254.s @@ -641,7 +641,7 @@ glabel L800A691C /* 0A7790 800A6B90 1000000A */ b .L800A6BBC /* 0A7794 800A6B94 00000000 */ nop .L800A6B98: -/* 0A7798 800A6B98 0C006D90 */ jal get_time_trial_ghost +/* 0A7798 800A6B98 0C006D90 */ jal timetrial_ghost_staff /* 0A779C 800A6B9C AFA70070 */ sw $a3, 0x70($sp) /* 0A77A0 800A6BA0 8FA70070 */ lw $a3, 0x70($sp) /* 0A77A4 800A6BA4 14400005 */ bnez $v0, .L800A6BBC diff --git a/asm/non_matchings/menu/func_80092188.s b/asm/non_matchings/menu/func_80092188.s index bc9b17b2..1b60105c 100644 --- a/asm/non_matchings/menu/func_80092188.s +++ b/asm/non_matchings/menu/func_80092188.s @@ -442,7 +442,7 @@ glabel L80092740 /* 0933BC 800927BC 00000000 */ nop /* 0933C0 800927C0 10800009 */ beqz $a0, .L800927E8 /* 0933C4 800927C4 244EFFFF */ addiu $t6, $v0, -1 -/* 0933C8 800927C8 0C001223 */ jal func_8000488C +/* 0933C8 800927C8 0C001223 */ jal sound_stop /* 0933CC 800927CC 00000000 */ nop /* 0933D0 800927D0 3C038012 */ lui $v1, %hi(D_80126830) # $v1, 0x8012 /* 0933D4 800927D4 3C02800E */ lui $v0, %hi(gTracksMenuTimeTrialHighlightIndex) # $v0, 0x800e @@ -466,7 +466,7 @@ glabel L80092740 /* 093414 80092814 24180001 */ li $t8, 1 /* 093418 80092818 10800003 */ beqz $a0, .L80092828 /* 09341C 8009281C AFB80034 */ sw $t8, 0x34($sp) -/* 093420 80092820 0C001223 */ jal func_8000488C +/* 093420 80092820 0C001223 */ jal sound_stop /* 093424 80092824 00000000 */ nop .L80092828: /* 093428 80092828 00002025 */ move $a0, $zero diff --git a/asm/non_matchings/object_functions/obj_loop_butterfly.s b/asm/non_matchings/object_functions/obj_loop_butterfly.s index 44f487be..c7e40e35 100644 --- a/asm/non_matchings/object_functions/obj_loop_butterfly.s +++ b/asm/non_matchings/object_functions/obj_loop_butterfly.s @@ -102,7 +102,7 @@ glabel L80040D30 /* 041984 80040D84 AFA8003C */ sw $t0, 0x3c($sp) /* 041988 80040D88 AFAF0014 */ sw $t7, 0x14($sp) /* 04198C 80040D8C AFAE0010 */ sw $t6, 0x10($sp) -/* 041990 80040D90 0C005B7A */ jal func_80016DE8 +/* 041990 80040D90 0C005B7A */ jal obj_dist_racer /* 041994 80040D94 46802320 */ cvt.s.w $f12, $f4 /* 041998 80040D98 0002C400 */ sll $t8, $v0, 0x10 /* 04199C 80040D9C 8FA8003C */ lw $t0, 0x3c($sp) @@ -129,7 +129,7 @@ glabel L80040D30 /* 0419EC 80040DEC 44065000 */ mfc1 $a2, $f10 /* 0419F0 80040DF0 AFA8003C */ sw $t0, 0x3c($sp) /* 0419F4 80040DF4 AFB80010 */ sw $t8, 0x10($sp) -/* 0419F8 80040DF8 0C005B1A */ jal func_80016C68 +/* 0419F8 80040DF8 0C005B1A */ jal obj_butterfly_node /* 0419FC 80040DFC 46804320 */ cvt.s.w $f12, $f8 /* 041A00 80040E00 8FA8003C */ lw $t0, 0x3c($sp) /* 041A04 80040E04 10400005 */ beqz $v0, .L80040E1C @@ -299,7 +299,7 @@ glabel L80040E54 /* 041C64 80041064 AFA8003C */ sw $t0, 0x3c($sp) /* 041C68 80041068 AFB80014 */ sw $t8, 0x14($sp) /* 041C6C 8004106C AFAF0010 */ sw $t7, 0x10($sp) -/* 041C70 80041070 0C005B7A */ jal func_80016DE8 +/* 041C70 80041070 0C005B7A */ jal obj_dist_racer /* 041C74 80041074 46803320 */ cvt.s.w $f12, $f6 /* 041C78 80041078 0002CC00 */ sll $t9, $v0, 0x10 /* 041C7C 8004107C 8FA8003C */ lw $t0, 0x3c($sp) @@ -327,7 +327,7 @@ glabel L80040E54 /* 041CD0 800410D0 AFA90038 */ sw $t1, 0x38($sp) /* 041CD4 800410D4 AFA8003C */ sw $t0, 0x3c($sp) /* 041CD8 800410D8 AFB90010 */ sw $t9, 0x10($sp) -/* 041CDC 800410DC 0C005B1A */ jal func_80016C68 +/* 041CDC 800410DC 0C005B1A */ jal obj_butterfly_node /* 041CE0 800410E0 46804320 */ cvt.s.w $f12, $f8 /* 041CE4 800410E4 8FA8003C */ lw $t0, 0x3c($sp) /* 041CE8 800410E8 8FA90038 */ lw $t1, 0x38($sp) @@ -464,7 +464,7 @@ glabel L800411E4 /* 041EE0 800412E0 AFA8003C */ sw $t0, 0x3c($sp) /* 041EE4 800412E4 AFAD0014 */ sw $t5, 0x14($sp) /* 041EE8 800412E8 AFAC0010 */ sw $t4, 0x10($sp) -/* 041EEC 800412EC 0C005B7A */ jal func_80016DE8 +/* 041EEC 800412EC 0C005B7A */ jal obj_dist_racer /* 041EF0 800412F0 46805320 */ cvt.s.w $f12, $f10 /* 041EF4 800412F4 00027400 */ sll $t6, $v0, 0x10 /* 041EF8 800412F8 8FA8003C */ lw $t0, 0x3c($sp) @@ -493,7 +493,7 @@ glabel L800411E4 /* 041F50 80041350 A7AA0072 */ sh $t2, 0x72($sp) /* 041F54 80041354 AFA8003C */ sw $t0, 0x3c($sp) /* 041F58 80041358 AFAD0010 */ sw $t5, 0x10($sp) -/* 041F5C 8004135C 0C005B1A */ jal func_80016C68 +/* 041F5C 8004135C 0C005B1A */ jal obj_butterfly_node /* 041F60 80041360 46804320 */ cvt.s.w $f12, $f8 /* 041F64 80041364 8FA8003C */ lw $t0, 0x3c($sp) /* 041F68 80041368 87AA0072 */ lh $t2, 0x72($sp) @@ -685,7 +685,7 @@ glabel L8004153C /* 04221C 8004161C AFAD0014 */ sw $t5, 0x14($sp) /* 042220 80041620 E7B0007C */ swc1 $f16, 0x7c($sp) /* 042224 80041624 AFA8003C */ sw $t0, 0x3c($sp) -/* 042228 80041628 0C005B7A */ jal func_80016DE8 +/* 042228 80041628 0C005B7A */ jal obj_dist_racer /* 04222C 8004162C AFAC0010 */ sw $t4, 0x10($sp) /* 042230 80041630 00022C00 */ sll $a1, $v0, 0x10 /* 042234 80041634 00021C00 */ sll $v1, $v0, 0x10 diff --git a/asm/non_matchings/objects/func_8000CC7C.s b/asm/non_matchings/objects/func_8000CC7C.s index 731988a7..9b2ca892 100644 --- a/asm/non_matchings/objects/func_8000CC7C.s +++ b/asm/non_matchings/objects/func_8000CC7C.s @@ -89,8 +89,8 @@ glabel func_8000CC7C /* 00D998 8000CD98 3C0B8012 */ lui $t3, %hi(D_8011ADC5) # $t3, 0x8012 /* 00D99C 8000CD9C 256BADC5 */ addiu $t3, %lo(D_8011ADC5) # addiu $t3, $t3, -0x523b /* 00D9A0 8000CDA0 816E0000 */ lb $t6, ($t3) -/* 00D9A4 8000CDA4 3C0C8012 */ lui $t4, %hi(D_8011AE82) # $t4, 0x8012 -/* 00D9A8 8000CDA8 258CAE82 */ addiu $t4, %lo(D_8011AE82) # addiu $t4, $t4, -0x517e +/* 00D9A4 8000CDA4 3C0C8012 */ lui $t4, %hi(gPrevTimeTrialVehicle) # $t4, 0x8012 +/* 00D9A8 8000CDA8 258CAE82 */ addiu $t4, %lo(gPrevTimeTrialVehicle) # addiu $t4, $t4, -0x517e /* 00D9AC 8000CDAC AFA20128 */ sw $v0, 0x128($sp) /* 00D9B0 8000CDB0 A58E0000 */ sh $t6, ($t4) /* 00D9B4 8000CDB4 92F80049 */ lbu $t8, 0x49($s7) @@ -1020,12 +1020,12 @@ glabel L8000D98C /* 00E694 8000DA94 26B50004 */ addiu $s5, $s5, 4 /* 00E698 8000DA98 00009025 */ move $s2, $zero .L8000DA9C: -/* 00E69C 8000DA9C 3C15800E */ lui $s5, %hi(gGhostObj) # $s5, 0x800e -/* 00E6A0 8000DAA0 26B5C718 */ addiu $s5, %lo(gGhostObj) # addiu $s5, $s5, -0x38e8 -/* 00E6A4 8000DAA4 0C0166D3 */ jal free_tt_ghost_data +/* 00E69C 8000DA9C 3C15800E */ lui $s5, %hi(gGhostObjStaff) # $s5, 0x800e +/* 00E6A0 8000DAA0 26B5C718 */ addiu $s5, %lo(gGhostObjStaff) # addiu $s5, $s5, -0x38e8 +/* 00E6A4 8000DAA4 0C0166D3 */ jal timetrial_free_staff_ghost /* 00E6A8 8000DAA8 AEA00000 */ sw $zero, ($s5) -/* 00E6AC 8000DAAC 3C118012 */ lui $s1, %hi(D_8011AD38) # $s1, 0x8012 -/* 00E6B0 8000DAB0 2631AD38 */ addiu $s1, %lo(D_8011AD38) # addiu $s1, $s1, -0x52c8 +/* 00E6AC 8000DAAC 3C118012 */ lui $s1, %hi(gTimeTrialContPak) # $s1, 0x8012 +/* 00E6B0 8000DAB0 2631AD38 */ addiu $s1, %lo(gTimeTrialContPak) # addiu $s1, $s1, -0x52c8 /* 00E6B4 8000DAB4 2418FFFF */ li $t8, -1 /* 00E6B8 8000DAB8 AE380000 */ sw $t8, ($s1) /* 00E6BC 8000DABC 3C0F8012 */ lui $t7, %hi(gIsTimeTrial) # $t7, 0x8012 @@ -1037,14 +1037,14 @@ glabel L8000D98C /* 00E6D4 8000DAD4 24010001 */ li $at, 1 /* 00E6D8 8000DAD8 15A1006D */ bne $t5, $at, .L8000DC90 /* 00E6DC 8000DADC 00000000 */ nop -/* 00E6E0 8000DAE0 0C016651 */ jal func_80059944 +/* 00E6E0 8000DAE0 0C016651 */ jal timetrial_reset_player_ghost /* 00E6E4 8000DAE4 00000000 */ nop -/* 00E6E8 8000DAE8 0C006D9A */ jal func_8001B668 +/* 00E6E8 8000DAE8 0C006D9A */ jal timetrial_init_player_ghost /* 00E6EC 8000DAEC 00002025 */ move $a0, $zero -/* 00E6F0 8000DAF0 3C10800E */ lui $s0, %hi(D_800DC728) # $s0, 0x800e +/* 00E6F0 8000DAF0 3C10800E */ lui $s0, %hi(gTimeTrialVehicle) # $s0, 0x800e /* 00E6F4 8000DAF4 AE220000 */ sw $v0, ($s1) /* 00E6F8 8000DAF8 3C01800E */ lui $at, %hi(gHasGhostToSave) # $at, 0x800e -/* 00E6FC 8000DAFC 2610C728 */ addiu $s0, %lo(D_800DC728) # addiu $s0, $s0, -0x38d8 +/* 00E6FC 8000DAFC 2610C728 */ addiu $s0, %lo(gTimeTrialVehicle) # addiu $s0, $s0, -0x38d8 /* 00E700 8000DB00 A020C730 */ sb $zero, %lo(gHasGhostToSave)($at) /* 00E704 8000DB04 860E0000 */ lh $t6, ($s0) /* 00E708 8000DB08 00000000 */ nop @@ -1053,12 +1053,12 @@ glabel L8000D98C /* 00E714 8000DB14 00000000 */ nop /* 00E718 8000DB18 A6000000 */ sh $zero, ($s0) .L8000DB1C: -/* 00E71C 8000DB1C 0C006CA2 */ jal func_8001B288 +/* 00E71C 8000DB1C 0C006CA2 */ jal timetrial_valid_player_ghost /* 00E720 8000DB20 00000000 */ nop /* 00E724 8000DB24 1040002C */ beqz $v0, .L8000DBD8 -/* 00E728 8000DB28 3C19800E */ lui $t9, %hi(D_800DC72C) # $t9, 0x800e +/* 00E728 8000DB28 3C19800E */ lui $t9, %hi(gTimeTrialCharacter) # $t9, 0x800e /* 00E72C 8000DB2C 860F0000 */ lh $t7, ($s0) -/* 00E730 8000DB30 8739C72C */ lh $t9, %lo(D_800DC72C)($t9) +/* 00E730 8000DB30 8739C72C */ lh $t9, %lo(gTimeTrialCharacter)($t9) /* 00E734 8000DB34 000F6880 */ sll $t5, $t7, 2 /* 00E738 8000DB38 01AF6821 */ addu $t5, $t5, $t7 /* 00E73C 8000DB3C 000D7080 */ sll $t6, $t5, 2 @@ -1091,10 +1091,10 @@ glabel L8000D98C /* 00E7A8 8000DBA8 3C01800E */ lui $at, %hi(D_800E5178) # $at, 0x800e /* 00E7AC 8000DBAC C4245178 */ lwc1 $f4, %lo(D_800E5178)($at) /* 00E7B0 8000DBB0 8C4E0050 */ lw $t6, 0x50($v0) -/* 00E7B4 8000DBB4 3C038012 */ lui $v1, %hi(D_8011AD34) # $v1, 0x8012 +/* 00E7B4 8000DBB4 3C038012 */ lui $v1, %hi(gGhostObjPlayer) # $v1, 0x8012 /* 00E7B8 8000DBB8 E5C40000 */ swc1 $f4, ($t6) /* 00E7BC 8000DBBC 8C59004C */ lw $t9, 0x4c($v0) -/* 00E7C0 8000DBC0 2463AD34 */ addiu $v1, %lo(D_8011AD34) # addiu $v1, $v1, -0x52cc +/* 00E7C0 8000DBC0 2463AD34 */ addiu $v1, %lo(gGhostObjPlayer) # addiu $v1, $v1, -0x52cc /* 00E7C4 8000DBC4 A7200014 */ sh $zero, 0x14($t9) /* 00E7C8 8000DBC8 AC620000 */ sw $v0, ($v1) /* 00E7CC 8000DBCC 8C530064 */ lw $s3, 0x64($v0) @@ -1103,7 +1103,7 @@ glabel L8000D98C .L8000DBD8: /* 00E7D8 8000DBD8 0C01AF62 */ jal get_current_map_id /* 00E7DC 8000DBDC 00000000 */ nop -/* 00E7E0 8000DBE0 0C006D3F */ jal func_8001B4FC +/* 00E7E0 8000DBE0 0C006D3F */ jal timetrial_init_staff_ghost /* 00E7E4 8000DBE4 00402025 */ move $a0, $v0 /* 00E7E8 8000DBE8 10400029 */ beqz $v0, .L8000DC90 /* 00E7EC 8000DBEC 3C188012 */ lui $t8, %hi(gMapDefaultVehicle) # $t8, 0x8012 @@ -1320,8 +1320,8 @@ glabel L8000D98C /* 00EAF8 8000DEF8 1653FFF5 */ bne $s2, $s3, .L8000DED0 /* 00EAFC 8000DEFC AC40003C */ sw $zero, 0x3c($v0) .L8000DF00: -/* 00EB00 8000DF00 3C018012 */ lui $at, %hi(D_8011AD4E) # $at, 0x8012 -/* 00EB04 8000DF04 A420AD4E */ sh $zero, %lo(D_8011AD4E)($at) +/* 00EB00 8000DF00 3C018012 */ lui $at, %hi(gRaceEndTimer) # $at, 0x8012 +/* 00EB04 8000DF04 A420AD4E */ sh $zero, %lo(gRaceEndTimer)($at) /* 00EB08 8000DF08 3C018012 */ lui $at, %hi(D_8011ADB4) # $at, 0x8012 /* 00EB0C 8000DF0C AC20ADB4 */ sw $zero, %lo(D_8011ADB4)($at) /* 00EB10 8000DF10 0C0274CC */ jal set_next_taj_challenge_menu diff --git a/asm/non_matchings/objects/func_800101AC.s b/asm/non_matchings/objects/func_800101AC.s index d0b6acd1..bb8142aa 100644 --- a/asm/non_matchings/objects/func_800101AC.s +++ b/asm/non_matchings/objects/func_800101AC.s @@ -303,13 +303,13 @@ glabel L800105A8 /* 0111C8 800105C8 1000000C */ b .L800105FC /* 0111CC 800105CC 24140012 */ li $s4, 18 glabel L800105D0 -/* 0111D0 800105D0 0C02B220 */ jal func_800AC880 +/* 0111D0 800105D0 0C02B220 */ jal lensflare_remove /* 0111D4 800105D4 02C02025 */ move $a0, $s6 /* 0111D8 800105D8 86C50048 */ lh $a1, 0x48($s6) /* 0111DC 800105DC 10000007 */ b .L800105FC /* 0111E0 800105E0 24140012 */ li $s4, 18 glabel L800105E4 -/* 0111E4 800105E4 0C02B3E6 */ jal func_800ACF98 +/* 0111E4 800105E4 0C02B3E6 */ jal lensflare_override_remove /* 0111E8 800105E8 02C02025 */ move $a0, $s6 /* 0111EC 800105EC 86C50048 */ lh $a1, 0x48($s6) /* 0111F0 800105F0 10000002 */ b .L800105FC @@ -342,7 +342,7 @@ glabel L8001063C /* 011248 80010648 00000000 */ nop /* 01124C 8001064C 10800006 */ beqz $a0, .L80010668 /* 011250 80010650 24010001 */ li $at, 1 -/* 011254 80010654 0C001223 */ jal func_8000488C +/* 011254 80010654 0C001223 */ jal sound_stop /* 011258 80010658 00000000 */ nop /* 01125C 8001065C 86C50048 */ lh $a1, 0x48($s6) /* 011260 80010660 00000000 */ nop @@ -358,35 +358,35 @@ glabel L80010664 /* 01127C 8001067C 00000000 */ nop /* 011280 80010680 10400003 */ beqz $v0, .L80010690 /* 011284 80010684 00000000 */ nop -/* 011288 80010688 0C001223 */ jal func_8000488C +/* 011288 80010688 0C001223 */ jal sound_stop /* 01128C 8001068C 00402025 */ move $a0, $v0 .L80010690: /* 011290 80010690 8E020010 */ lw $v0, 0x10($s0) /* 011294 80010694 00000000 */ nop /* 011298 80010698 10400003 */ beqz $v0, .L800106A8 /* 01129C 8001069C 00000000 */ nop -/* 0112A0 800106A0 0C001223 */ jal func_8000488C +/* 0112A0 800106A0 0C001223 */ jal sound_stop /* 0112A4 800106A4 00402025 */ move $a0, $v0 .L800106A8: /* 0112A8 800106A8 8E020014 */ lw $v0, 0x14($s0) /* 0112AC 800106AC 00000000 */ nop /* 0112B0 800106B0 10400003 */ beqz $v0, .L800106C0 /* 0112B4 800106B4 00000000 */ nop -/* 0112B8 800106B8 0C001223 */ jal func_8000488C +/* 0112B8 800106B8 0C001223 */ jal sound_stop /* 0112BC 800106BC 00402025 */ move $a0, $v0 .L800106C0: /* 0112C0 800106C0 8E02001C */ lw $v0, 0x1c($s0) /* 0112C4 800106C4 00000000 */ nop /* 0112C8 800106C8 10400003 */ beqz $v0, .L800106D8 /* 0112CC 800106CC 00000000 */ nop -/* 0112D0 800106D0 0C001223 */ jal func_8000488C +/* 0112D0 800106D0 0C001223 */ jal sound_stop /* 0112D4 800106D4 00402025 */ move $a0, $v0 .L800106D8: /* 0112D8 800106D8 8E020020 */ lw $v0, 0x20($s0) /* 0112DC 800106DC 00000000 */ nop /* 0112E0 800106E0 10400003 */ beqz $v0, .L800106F0 /* 0112E4 800106E4 00000000 */ nop -/* 0112E8 800106E8 0C001223 */ jal func_8000488C +/* 0112E8 800106E8 0C001223 */ jal sound_stop /* 0112EC 800106EC 00402025 */ move $a0, $v0 .L800106F0: /* 0112F0 800106F0 8E040024 */ lw $a0, 0x24($s0) @@ -407,7 +407,7 @@ glabel L80010664 /* 011324 80010724 00000000 */ nop /* 011328 80010728 10800003 */ beqz $a0, .L80010738 /* 01132C 8001072C 00000000 */ nop -/* 011330 80010730 0C001223 */ jal func_8000488C +/* 011330 80010730 0C001223 */ jal sound_stop /* 011334 80010734 00000000 */ nop .L80010738: /* 011338 80010738 0C001AB2 */ jal racer_sound_free diff --git a/asm/non_matchings/objects/func_80010994.s b/asm/non_matchings/objects/func_80010994.s index ab748f92..5b33326e 100644 --- a/asm/non_matchings/objects/func_80010994.s +++ b/asm/non_matchings/objects/func_80010994.s @@ -405,16 +405,16 @@ glabel func_80010994 .L80010F58: /* 011B58 80010F58 0C0079BB */ jal func_8001E6EC /* 011B5C 80010F5C 00002025 */ move $a0, $zero -/* 011B60 80010F60 3C188012 */ lui $t8, %hi(D_8011AEF7) # $t8, 0x8012 -/* 011B64 80010F64 8318AEF7 */ lb $t8, %lo(D_8011AEF7)($t8) +/* 011B60 80010F60 3C188012 */ lui $t8, %hi(gTajRaceInit) # $t8, 0x8012 +/* 011B64 80010F64 8318AEF7 */ lb $t8, %lo(gTajRaceInit)($t8) /* 011B68 80010F68 00000000 */ nop /* 011B6C 80010F6C 13000003 */ beqz $t8, .L80010F7C /* 011B70 80010F70 00000000 */ nop -/* 011B74 80010F74 0C008A52 */ jal func_80022948 +/* 011B74 80010F74 0C008A52 */ jal mode_init_taj_race /* 011B78 80010F78 00000000 */ nop .L80010F7C: -/* 011B7C 80010F7C 3C108012 */ lui $s0, %hi(D_8011ADAC) # $s0, 0x8012 -/* 011B80 80010F80 2610ADAC */ addiu $s0, %lo(D_8011ADAC) # addiu $s0, $s0, -0x5254 +/* 011B7C 80010F7C 3C108012 */ lui $s0, %hi(gPathUpdateOff) # $s0, 0x8012 +/* 011B80 80010F80 2610ADAC */ addiu $s0, %lo(gPathUpdateOff) # addiu $s0, $s0, -0x5254 /* 011B84 80010F84 8E190000 */ lw $t9, ($s0) /* 011B88 80010F88 00000000 */ nop /* 011B8C 80010F8C 17200009 */ bnez $t9, .L80010FB4 @@ -423,17 +423,17 @@ glabel func_80010994 /* 011B98 80010F98 00000000 */ nop /* 011B9C 80010F9C 0C005FA6 */ jal func_80017E98 /* 011BA0 80010FA0 00000000 */ nop -/* 011BA4 80010FA4 0C006F15 */ jal func_8001BC54 +/* 011BA4 80010FA4 0C006F15 */ jal spectate_update /* 011BA8 80010FA8 00000000 */ nop /* 011BAC 80010FAC 0C007A4F */ jal func_8001E93C /* 011BB0 80010FB0 00000000 */ nop .L80010FB4: /* 011BB4 80010FB4 3C078012 */ lui $a3, %hi(gNumRacers) # $a3, 0x8012 /* 011BB8 80010FB8 8CE7AEF0 */ lw $a3, %lo(gNumRacers)($a3) -/* 011BBC 80010FBC 3C098012 */ lui $t1, %hi(D_8011AD4E) # $t1, 0x8012 +/* 011BBC 80010FBC 3C098012 */ lui $t1, %hi(gRaceEndTimer) # $t1, 0x8012 /* 011BC0 80010FC0 10E00010 */ beqz $a3, .L80011004 /* 011BC4 80010FC4 00000000 */ nop -/* 011BC8 80010FC8 8529AD4E */ lh $t1, %lo(D_8011AD4E)($t1) +/* 011BC8 80010FC8 8529AD4E */ lh $t1, %lo(gRaceEndTimer)($t1) /* 011BCC 80010FCC 00000000 */ nop /* 011BD0 80010FD0 15200007 */ bnez $t1, .L80010FF0 /* 011BD4 80010FD4 00000000 */ nop @@ -444,7 +444,7 @@ glabel func_80010994 /* 011BE8 80010FE8 10000006 */ b .L80011004 /* 011BEC 80010FEC 00000000 */ nop .L80010FF0: -/* 011BF0 80010FF0 0C006A3D */ jal func_8001A8F4 +/* 011BF0 80010FF0 0C006A3D */ jal race_transition_adventure /* 011BF4 80010FF4 02802025 */ move $a0, $s4 /* 011BF8 80010FF8 3C078012 */ lui $a3, %hi(gNumRacers) # $a3, 0x8012 /* 011BFC 80010FFC 8CE7AEF0 */ lw $a3, %lo(gNumRacers)($a3) diff --git a/asm/non_matchings/objects/func_80019808.s b/asm/non_matchings/objects/func_80019808.s index 4c0bc99c..09a665b2 100644 --- a/asm/non_matchings/objects/func_80019808.s +++ b/asm/non_matchings/objects/func_80019808.s @@ -471,7 +471,7 @@ glabel func_80019808 /* 01AABC 80019EBC 2406FFFF */ li $a2, -1 /* 01AAC0 80019EC0 0C01B06B */ jal push_level_property_stack /* 01AAC4 80019EC4 24E7FFFF */ addiu $a3, $a3, -1 -/* 01AAC8 80019EC8 0C006A35 */ jal func_8001A8D4 +/* 01AAC8 80019EC8 0C006A35 */ jal race_finish_adventure /* 01AACC 80019ECC 02802025 */ move $a0, $s4 .L80019ED0: /* 01AAD0 80019ED0 3C018012 */ lui $at, %hi(D_8011ADB4) # $at, 0x8012 @@ -792,7 +792,7 @@ glabel func_80019808 /* 01AF4C 8001A34C 3C0F8012 */ lui $t7, %hi(D_8011AD3C) # $t7, 0x8012 /* 01AF50 8001A350 13000005 */ beqz $t8, .L8001A368 /* 01AF54 8001A354 00000000 */ nop -/* 01AF58 8001A358 0C008B86 */ jal func_80022E18 +/* 01AF58 8001A358 0C008B86 */ jal mode_end_taj_race /* 01AF5C 8001A35C 00002025 */ move $a0, $zero /* 01AF60 8001A360 10000114 */ b .L8001A7B4 /* 01AF64 8001A364 8FBF0034 */ lw $ra, 0x34($sp) @@ -1088,7 +1088,7 @@ glabel func_80019808 /* 01B384 8001A784 25D90001 */ addiu $t9, $t6, 1 /* 01B388 8001A788 A4590000 */ sh $t9, ($v0) .L8001A78C: -/* 01B38C 8001A78C 0C006A35 */ jal func_8001A8D4 +/* 01B38C 8001A78C 0C006A35 */ jal race_finish_adventure /* 01B390 8001A790 02802025 */ move $a0, $s4 .L8001A794: /* 01B394 8001A794 3C018012 */ lui $at, %hi(D_8011ADB4) # $at, 0x8012 @@ -1096,7 +1096,7 @@ glabel func_80019808 /* 01B39C 8001A79C AC35ADB4 */ sw $s5, %lo(D_8011ADB4)($at) /* 01B3A0 8001A7A0 14540004 */ bne $v0, $s4, .L8001A7B4 /* 01B3A4 8001A7A4 8FBF0034 */ lw $ra, 0x34($sp) -/* 01B3A8 8001A7A8 0C006B99 */ jal func_8001AE64 +/* 01B3A8 8001A7A8 0C006B99 */ jal race_finish_time_trial /* 01B3AC 8001A7AC 00000000 */ nop .L8001A7B0: /* 01B3B0 8001A7B0 8FBF0034 */ lw $ra, 0x34($sp) diff --git a/asm/non_matchings/objects/func_8001C6C4.s b/asm/non_matchings/objects/func_8001C6C4.s index 8509cfb7..2a46647f 100644 --- a/asm/non_matchings/objects/func_8001C6C4.s +++ b/asm/non_matchings/objects/func_8001C6C4.s @@ -62,7 +62,7 @@ glabel func_8001C6C4 /* 01D384 8001C784 8FBF005C */ lw $ra, 0x5c($sp) .L8001C788: /* 01D388 8001C788 AFA50080 */ sw $a1, 0x80($sp) -/* 01D38C 8001C78C 0C007485 */ jal func_8001D214 +/* 01D38C 8001C78C 0C007485 */ jal ainode_get /* 01D390 8001C790 AFA6006C */ sw $a2, 0x6c($sp) /* 01D394 8001C794 8FA50080 */ lw $a1, 0x80($sp) /* 01D398 8001C798 8FA6006C */ lw $a2, 0x6c($sp) diff --git a/asm/non_matchings/objects/func_8001CC48.s b/asm/non_matchings/objects/func_8001CC48.s index 0d57639e..0cb356a5 100644 --- a/asm/non_matchings/objects/func_8001CC48.s +++ b/asm/non_matchings/objects/func_8001CC48.s @@ -6,12 +6,12 @@ glabel func_8001CC48 /* 01D858 8001CC58 00A08025 */ move $s0, $a1 /* 01D85C 8001CC5C 28810080 */ slti $at, $a0, 0x80 /* 01D860 8001CC60 14200003 */ bnez $at, .L8001CC70 -/* 01D864 8001CC64 3C0E8012 */ lui $t6, %hi(D_8011AF04) # $t6, 0x8012 +/* 01D864 8001CC64 3C0E8012 */ lui $t6, %hi(gAINodes) # $t6, 0x8012 .L8001CC68: /* 01D868 8001CC68 1000002C */ b .L8001CD1C /* 01D86C 8001CC6C 240200FF */ li $v0, 255 .L8001CC70: -/* 01D870 8001CC70 8DCEAF04 */ lw $t6, %lo(D_8011AF04)($t6) +/* 01D870 8001CC70 8DCEAF04 */ lw $t6, %lo(gAINodes)($t6) /* 01D874 8001CC74 00047880 */ sll $t7, $a0, 2 /* 01D878 8001CC78 01CFC021 */ addu $t8, $t6, $t7 /* 01D87C 8001CC7C 8F020000 */ lw $v0, ($t8) diff --git a/asm/non_matchings/objects/func_8001CD28.s b/asm/non_matchings/objects/func_8001CD28.s index ba452d7e..a625f991 100644 --- a/asm/non_matchings/objects/func_8001CD28.s +++ b/asm/non_matchings/objects/func_8001CD28.s @@ -26,8 +26,8 @@ glabel func_8001CD28 /* 01D984 8001CD84 1420FFF9 */ bnez $at, .L8001CD6C /* 01D988 8001CD88 ADE00000 */ sw $zero, ($t7) /* 01D98C 8001CD8C 8FAE0378 */ lw $t6, 0x378($sp) -/* 01D990 8001CD90 3C038012 */ lui $v1, %hi(D_8011AF04) # $v1, 0x8012 -/* 01D994 8001CD94 8C63AF04 */ lw $v1, %lo(D_8011AF04)($v1) +/* 01D990 8001CD90 3C038012 */ lui $v1, %hi(gAINodes) # $v1, 0x8012 +/* 01D994 8001CD94 8C63AF04 */ lw $v1, %lo(gAINodes)($v1) /* 01D998 8001CD98 000E7880 */ sll $t7, $t6, 2 /* 01D99C 8001CD9C 006F2021 */ addu $a0, $v1, $t7 /* 01D9A0 8001CDA0 8C820000 */ lw $v0, ($a0) diff --git a/asm/non_matchings/objects/func_8001F460.s b/asm/non_matchings/objects/func_8001F460.s index 0abffc88..68a62371 100644 --- a/asm/non_matchings/objects/func_8001F460.s +++ b/asm/non_matchings/objects/func_8001F460.s @@ -179,7 +179,7 @@ glabel func_8001F460 /* 0202C4 8001F6C4 00000000 */ nop /* 0202C8 8001F6C8 10800012 */ beqz $a0, .L8001F714 /* 0202CC 8001F6CC 00000000 */ nop -/* 0202D0 8001F6D0 0C001223 */ jal func_8000488C +/* 0202D0 8001F6D0 0C001223 */ jal sound_stop /* 0202D4 8001F6D4 00000000 */ nop /* 0202D8 8001F6D8 1000000F */ b .L8001F718 /* 0202DC 8001F6DC A2600038 */ sb $zero, 0x38($s3) @@ -188,7 +188,7 @@ glabel func_8001F460 /* 0202E4 8001F6E4 00000000 */ nop /* 0202E8 8001F6E8 10800007 */ beqz $a0, .L8001F708 /* 0202EC 8001F6EC 00000000 */ nop -/* 0202F0 8001F6F0 0C001223 */ jal func_8000488C +/* 0202F0 8001F6F0 0C001223 */ jal sound_stop /* 0202F4 8001F6F4 00000000 */ nop /* 0202F8 8001F6F8 82620038 */ lb $v0, 0x38($s3) /* 0202FC 8001F6FC 00000000 */ nop @@ -1930,7 +1930,7 @@ glabel func_8001F460 /* 021C7C 8002107C 02C02025 */ move $a0, $s6 /* 021C80 80021080 AECF0074 */ sw $t7, 0x74($s6) /* 021C84 80021084 8FA5019C */ lw $a1, 0x19c($sp) -/* 021C88 80021088 0C02BF0F */ jal func_800AFC3C +/* 021C88 80021088 0C02BF0F */ jal obj_spawn_particle /* 021C8C 8002108C 00000000 */ nop /* 021C90 80021090 00001025 */ move $v0, $zero .L80021094: diff --git a/asm/non_matchings/objects/spawn_object.s b/asm/non_matchings/objects/spawn_object.s index b09738e6..df8a0a1c 100644 --- a/asm/non_matchings/objects/spawn_object.s +++ b/asm/non_matchings/objects/spawn_object.s @@ -575,7 +575,7 @@ glabel L8000EDE0 /* 00FE80 8000F280 00C02825 */ move $a1, $a2 /* 00FE84 8000F284 19800006 */ blez $t4, .L8000F2A0 /* 00FE88 8000F288 00000000 */ nop -/* 00FE8C 8000F28C 0C003EB1 */ jal func_8000FAC4 +/* 00FE8C 8000F28C 0C003EB1 */ jal obj_init_emitter /* 00FE90 8000F290 AFA60048 */ sw $a2, 0x48($sp) /* 00FE94 8000F294 8FA60048 */ lw $a2, 0x48($sp) /* 00FE98 8000F298 8E500040 */ lw $s0, 0x40($s2) diff --git a/asm/non_matchings/racer/func_80042D20.s b/asm/non_matchings/racer/func_80042D20.s index 2f183ecc..d89c4579 100644 --- a/asm/non_matchings/racer/func_80042D20.s +++ b/asm/non_matchings/racer/func_80042D20.s @@ -63,7 +63,7 @@ glabel func_80042D20 .L80042D98: /* 043998 80042D98 A60001C6 */ sh $zero, 0x1c6($s0) .L80042D9C: -/* 04399C 80042D9C 0C006B91 */ jal func_8001AE44 +/* 04399C 80042D9C 0C006B91 */ jal race_finish_timer /* 0439A0 80042DA0 AFAA0060 */ sw $t2, 0x60($sp) /* 0439A4 80042DA4 8FAA0060 */ lw $t2, 0x60($sp) /* 0439A8 80042DA8 10400007 */ beqz $v0, .L80042DC8 diff --git a/asm/non_matchings/racer/func_8004447C.s b/asm/non_matchings/racer/func_8004447C.s index 96947e56..716e34f5 100644 --- a/asm/non_matchings/racer/func_8004447C.s +++ b/asm/non_matchings/racer/func_8004447C.s @@ -44,12 +44,12 @@ glabel func_8004447C /* 0450FC 800444FC C44C000C */ lwc1 $f12, 0xc($v0) /* 045100 80044500 C44E0010 */ lwc1 $f14, 0x10($v0) /* 045104 80044504 8C460014 */ lw $a2, 0x14($v0) -/* 045108 80044508 0C007149 */ jal func_8001C524 +/* 045108 80044508 0C007149 */ jal ainode_find_nearest /* 04510C 8004450C 00003825 */ move $a3, $zero /* 045110 80044510 240100FF */ li $at, 255 /* 045114 80044514 10410008 */ beq $v0, $at, .L80044538 /* 045118 80044518 AFA20058 */ sw $v0, 0x58($sp) -/* 04511C 8004451C 0C007485 */ jal func_8001D214 +/* 04511C 8004451C 0C007485 */ jal ainode_get /* 045120 80044520 00402025 */ move $a0, $v0 /* 045124 80044524 240C0001 */ li $t4, 1 /* 045128 80044528 240D00FF */ li $t5, 255 @@ -142,7 +142,7 @@ glabel func_8004447C .L80044664: /* 045264 80044664 00000000 */ nop /* 045268 80044668 C58C0010 */ lwc1 $f12, 0x10($t4) -/* 04526C 8004466C 0C007106 */ jal func_8001C418 +/* 04526C 8004466C 0C007106 */ jal obj_elevation /* 045270 80044670 AFA60074 */ sw $a2, 0x74($sp) /* 045274 80044674 920301CD */ lbu $v1, 0x1cd($s0) /* 045278 80044678 8FA60074 */ lw $a2, 0x74($sp) @@ -459,7 +459,7 @@ glabel L80044ADC /* 0456E8 80044AE8 00000000 */ nop /* 0456EC 80044AEC 82030212 */ lb $v1, 0x212($s0) /* 0456F0 80044AF0 AFA60074 */ sw $a2, 0x74($sp) -/* 0456F4 80044AF4 0C007485 */ jal func_8001D214 +/* 0456F4 80044AF4 0C007485 */ jal ainode_get /* 0456F8 80044AF8 A7A3004E */ sh $v1, 0x4e($sp) /* 0456FC 80044AFC 8FAB006C */ lw $t3, 0x6c($sp) /* 045700 80044B00 8C4A003C */ lw $t2, 0x3c($v0) @@ -677,7 +677,7 @@ glabel L80044ADC /* 045A08 80044E08 C50C000C */ lwc1 $f12, 0xc($t0) /* 045A0C 80044E0C C50E0010 */ lwc1 $f14, 0x10($t0) /* 045A10 80044E10 8D060014 */ lw $a2, 0x14($t0) -/* 045A14 80044E14 0C007149 */ jal func_8001C524 +/* 045A14 80044E14 0C007149 */ jal ainode_find_nearest /* 045A18 80044E18 00003825 */ move $a3, $zero /* 045A1C 80044E1C AFA20058 */ sw $v0, 0x58($sp) /* 045A20 80044E20 8FAD006C */ lw $t5, 0x6c($sp) @@ -713,7 +713,7 @@ glabel L80044ADC /* 045A88 80044E88 10410008 */ beq $v0, $at, .L80044EAC /* 045A8C 80044E8C 00000000 */ nop /* 045A90 80044E90 8FA40058 */ lw $a0, 0x58($sp) -/* 045A94 80044E94 0C007485 */ jal func_8001D214 +/* 045A94 80044E94 0C007485 */ jal ainode_get /* 045A98 80044E98 00000000 */ nop /* 045A9C 80044E9C AE020158 */ sw $v0, 0x158($s0) /* 045AA0 80044EA0 8FAB006C */ lw $t3, 0x6c($sp) @@ -724,7 +724,7 @@ glabel L80044ADC /* 045AB0 80044EB0 240100FF */ li $at, 255 /* 045AB4 80044EB4 10810007 */ beq $a0, $at, .L80044ED4 /* 045AB8 80044EB8 00000000 */ nop -/* 045ABC 80044EBC 0C007485 */ jal func_8001D214 +/* 045ABC 80044EBC 0C007485 */ jal ainode_get /* 045AC0 80044EC0 00000000 */ nop /* 045AC4 80044EC4 AE020158 */ sw $v0, 0x158($s0) /* 045AC8 80044EC8 8FAB006C */ lw $t3, 0x6c($sp) @@ -773,13 +773,13 @@ glabel L80044F54 /* 045B5C 80044F5C C5EC000C */ lwc1 $f12, 0xc($t7) /* 045B60 80044F60 C5EE0010 */ lwc1 $f14, 0x10($t7) /* 045B64 80044F64 8DE60014 */ lw $a2, 0x14($t7) -/* 045B68 80044F68 0C007149 */ jal func_8001C524 +/* 045B68 80044F68 0C007149 */ jal ainode_find_nearest /* 045B6C 80044F6C 00000000 */ nop /* 045B70 80044F70 240100FF */ li $at, 255 /* 045B74 80044F74 24050001 */ li $a1, 1 /* 045B78 80044F78 10410008 */ beq $v0, $at, .L80044F9C /* 045B7C 80044F7C AFA20058 */ sw $v0, 0x58($sp) -/* 045B80 80044F80 0C007485 */ jal func_8001D214 +/* 045B80 80044F80 0C007485 */ jal ainode_get /* 045B84 80044F84 00402025 */ move $a0, $v0 /* 045B88 80044F88 24050001 */ li $a1, 1 /* 045B8C 80044F8C 241800FF */ li $t8, 255 diff --git a/asm/non_matchings/racer/func_8004F7F4.s b/asm/non_matchings/racer/func_8004F7F4.s index 1c6a55fa..640a21aa 100644 --- a/asm/non_matchings/racer/func_8004F7F4.s +++ b/asm/non_matchings/racer/func_8004F7F4.s @@ -299,7 +299,7 @@ glabel func_8004F7F4 /* 0507F4 8004FBF4 00000000 */ nop /* 0507F8 8004FBF8 10400004 */ beqz $v0, .L8004FC0C /* 0507FC 8004FBFC 00000000 */ nop -/* 050800 8004FC00 0C001223 */ jal func_8000488C +/* 050800 8004FC00 0C001223 */ jal sound_stop /* 050804 8004FC04 00402025 */ move $a0, $v0 /* 050808 8004FC08 AE00001C */ sw $zero, 0x1c($s0) .L8004FC0C: diff --git a/asm/non_matchings/racer/func_80050A28.s b/asm/non_matchings/racer/func_80050A28.s index 3f50f3f7..8d06f0ec 100644 --- a/asm/non_matchings/racer/func_80050A28.s +++ b/asm/non_matchings/racer/func_80050A28.s @@ -588,7 +588,7 @@ glabel func_80050A28 /* 051DF0 800511F0 00000000 */ nop /* 051DF4 800511F4 10400003 */ beqz $v0, .L80051204 /* 051DF8 800511F8 00000000 */ nop -/* 051DFC 800511FC 0C001223 */ jal func_8000488C +/* 051DFC 800511FC 0C001223 */ jal sound_stop /* 051E00 80051200 00402025 */ move $a0, $v0 .L80051204: /* 051E04 80051204 10000015 */ b .L8005125C @@ -598,7 +598,7 @@ glabel func_80050A28 /* 051E10 80051210 00000000 */ nop /* 051E14 80051214 10400011 */ beqz $v0, .L8005125C /* 051E18 80051218 00000000 */ nop -/* 051E1C 8005121C 0C001223 */ jal func_8000488C +/* 051E1C 8005121C 0C001223 */ jal sound_stop /* 051E20 80051220 00402025 */ move $a0, $v0 /* 051E24 80051224 1000000D */ b .L8005125C /* 051E28 80051228 00000000 */ nop @@ -607,14 +607,14 @@ glabel func_80050A28 /* 051E30 80051230 00000000 */ nop /* 051E34 80051234 10400003 */ beqz $v0, .L80051244 /* 051E38 80051238 00000000 */ nop -/* 051E3C 8005123C 0C001223 */ jal func_8000488C +/* 051E3C 8005123C 0C001223 */ jal sound_stop /* 051E40 80051240 00402025 */ move $a0, $v0 .L80051244: /* 051E44 80051244 8E020014 */ lw $v0, 0x14($s0) /* 051E48 80051248 00000000 */ nop /* 051E4C 8005124C 10400003 */ beqz $v0, .L8005125C /* 051E50 80051250 00000000 */ nop -/* 051E54 80051254 0C001223 */ jal func_8000488C +/* 051E54 80051254 0C001223 */ jal sound_stop /* 051E58 80051258 00402025 */ move $a0, $v0 .L8005125C: /* 051E5C 8005125C 3C028012 */ lui $v0, %hi(gCurrentRacerInput) # $v0, 0x8012 @@ -1255,7 +1255,7 @@ glabel func_80050A28 /* 0527AC 80051BAC 45000006 */ bc1f .L80051BC8 .L80051BB0: /* 0527B0 80051BB0 00402025 */ move $a0, $v0 -/* 0527B4 80051BB4 0C001223 */ jal func_8000488C +/* 0527B4 80051BB4 0C001223 */ jal sound_stop /* 0527B8 80051BB8 AFA90064 */ sw $t1, 0x64($sp) /* 0527BC 80051BBC 8FA90064 */ lw $t1, 0x64($sp) /* 0527C0 80051BC0 8FA60078 */ lw $a2, 0x78($sp) diff --git a/asm/non_matchings/racer/set_ghost_position_and_rotation.s b/asm/non_matchings/racer/set_ghost_position_and_rotation.s index 55b7a359..30799e83 100644 --- a/asm/non_matchings/racer/set_ghost_position_and_rotation.s +++ b/asm/non_matchings/racer/set_ghost_position_and_rotation.s @@ -6,15 +6,15 @@ glabel D_800E6938 .text glabel set_ghost_position_and_rotation -/* 05AA40 80059E40 3C058012 */ lui $a1, %hi(D_8011D59C) # $a1, 0x8012 -/* 05AA44 80059E44 80A5D59C */ lb $a1, %lo(D_8011D59C)($a1) +/* 05AA40 80059E40 3C058012 */ lui $a1, %hi(gCurrentGhostIndex) # $a1, 0x8012 +/* 05AA44 80059E44 80A5D59C */ lb $a1, %lo(gCurrentGhostIndex)($a1) /* 05AA48 80059E48 27BDFF68 */ addiu $sp, $sp, -0x98 /* 05AA4C 80059E4C 24A50001 */ addiu $a1, $a1, 1 /* 05AA50 80059E50 AFBF001C */ sw $ra, 0x1c($sp) /* 05AA54 80059E54 AFB00018 */ sw $s0, 0x18($sp) /* 05AA58 80059E58 30AE0001 */ andi $t6, $a1, 1 /* 05AA5C 80059E5C 00808025 */ move $s0, $a0 -/* 05AA60 80059E60 0C006CEB */ jal is_time_trial_ghost +/* 05AA60 80059E60 0C006CEB */ jal timetrial_staff_ghost_check /* 05AA64 80059E64 AFAE005C */ sw $t6, 0x5c($sp) /* 05AA68 80059E68 8FA5005C */ lw $a1, 0x5c($sp) /* 05AA6C 80059E6C 10400002 */ beqz $v0, .L80059E78 @@ -45,13 +45,13 @@ glabel set_ghost_position_and_rotation /* 05AACC 80059ECC 462020A0 */ cvt.s.d $f2, $f4 .L80059ED0: /* 05AAD0 80059ED0 4459F800 */ cfc1 $t9, $31 -/* 05AAD4 80059ED4 3C0D8012 */ lui $t5, %hi(D_8011D5A0) # $t5, 0x8012 +/* 05AAD4 80059ED4 3C0D8012 */ lui $t5, %hi(gGhostNodeCount) # $t5, 0x8012 /* 05AAD8 80059ED8 37210003 */ ori $at, $t9, 3 /* 05AADC 80059EDC 38210002 */ xori $at, $at, 2 /* 05AAE0 80059EE0 44C1F800 */ ctc1 $at, $31 /* 05AAE4 80059EE4 01AE6821 */ addu $t5, $t5, $t6 /* 05AAE8 80059EE8 460011A4 */ cvt.w.s $f6, $f2 -/* 05AAEC 80059EEC 85ADD5A0 */ lh $t5, %lo(D_8011D5A0)($t5) +/* 05AAEC 80059EEC 85ADD5A0 */ lh $t5, %lo(gGhostNodeCount)($t5) /* 05AAF0 80059EF0 44033000 */ mfc1 $v1, $f6 /* 05AAF4 80059EF4 25AFFFFE */ addiu $t7, $t5, -2 /* 05AAF8 80059EF8 44D9F800 */ ctc1 $t9, $31 @@ -69,8 +69,8 @@ glabel set_ghost_position_and_rotation /* 05AB24 80059F24 AFAD004C */ sw $t5, 0x4c($sp) /* 05AB28 80059F28 0C01AF62 */ jal get_current_map_id /* 05AB2C 80059F2C E7A20094 */ swc1 $f2, 0x94($sp) -/* 05AB30 80059F30 3C188012 */ lui $t8, %hi(D_8011D5AC) # $t8, 0x8012 -/* 05AB34 80059F34 8718D5AC */ lh $t8, %lo(D_8011D5AC)($t8) +/* 05AB30 80059F30 3C188012 */ lui $t8, %hi(gGhostMapID) # $t8, 0x8012 +/* 05AB34 80059F34 8718D5AC */ lh $t8, %lo(gGhostMapID)($t8) /* 05AB38 80059F38 8FA3003C */ lw $v1, 0x3c($sp) /* 05AB3C 80059F3C 8FA5005C */ lw $a1, 0x5c($sp) /* 05AB40 80059F40 8FAD004C */ lw $t5, 0x4c($sp) diff --git a/asm/non_matchings/tracks/func_800278E8.s b/asm/non_matchings/tracks/func_800278E8.s index 45cf2f95..4017383c 100644 --- a/asm/non_matchings/tracks/func_800278E8.s +++ b/asm/non_matchings/tracks/func_800278E8.s @@ -23,7 +23,7 @@ glabel func_800278E8 /* 028538 80027938 AFAF0030 */ sw $t7, 0x30($sp) /* 02853C 8002793C 8E040000 */ lw $a0, ($s0) /* 028540 80027940 AFA60034 */ sw $a2, 0x34($sp) -/* 028544 80027944 0C006F75 */ jal find_nearest_spectate_camera +/* 028544 80027944 0C006F75 */ jal spectate_nearest /* 028548 80027948 AFA30040 */ sw $v1, 0x40($sp) /* 02854C 8002794C 8FB80030 */ lw $t8, 0x30($sp) /* 028550 80027950 823901D8 */ lb $t9, 0x1d8($s1) @@ -75,7 +75,7 @@ glabel func_800278E8 /* 0285F0 800279F0 00000000 */ nop .L800279F4: /* 0285F4 800279F4 822401FD */ lb $a0, 0x1fd($s1) -/* 0285F8 800279F8 0C006F65 */ jal get_camera_object +/* 0285F8 800279F8 0C006F65 */ jal spectate_object /* 0285FC 800279FC AFA50054 */ sw $a1, 0x54($sp) /* 028600 80027A00 3C0F8012 */ lui $t7, %hi(D_8011B104) # $t7, 0x8012 /* 028604 80027A04 8DEFB104 */ lw $t7, %lo(D_8011B104)($t7) diff --git a/asm/non_matchings/weather/func_800ACA20.s b/asm/non_matchings/weather/func_800ACA20.s index d8bfb922..603489cd 100644 --- a/asm/non_matchings/weather/func_800ACA20.s +++ b/asm/non_matchings/weather/func_800ACA20.s @@ -1,8 +1,8 @@ glabel func_800ACA20 /* 0AD620 800ACA20 27BDFF10 */ addiu $sp, $sp, -0xf0 /* 0AD624 800ACA24 AFB60050 */ sw $s6, 0x50($sp) -/* 0AD628 800ACA28 3C16800E */ lui $s6, %hi(D_800E2A80) # $s6, 0x800e -/* 0AD62C 800ACA2C 26D62A80 */ addiu $s6, %lo(D_800E2A80) # addiu $s6, $s6, 0x2a80 +/* 0AD628 800ACA28 3C16800E */ lui $s6, %hi(gLensFlare) # $s6, 0x800e +/* 0AD62C 800ACA2C 26D62A80 */ addiu $s6, %lo(gLensFlare) # addiu $s6, $s6, 0x2a80 /* 0AD630 800ACA30 8ECF0000 */ lw $t7, ($s6) /* 0AD634 800ACA34 AFB70054 */ sw $s7, 0x54($sp) /* 0AD638 800ACA38 AFB5004C */ sw $s5, 0x4c($sp) @@ -24,8 +24,8 @@ glabel func_800ACA20 /* 0AD678 800ACA78 E7B50020 */ swc1 $f21, 0x20($sp) /* 0AD67C 800ACA7C 11E00126 */ beqz $t7, .L800ACF18 /* 0AD680 800ACA80 E7B40024 */ swc1 $f20, 0x24($sp) -/* 0AD684 800ACA84 3C19800E */ lui $t9, %hi(D_800E2A84) # $t9, 0x800e -/* 0AD688 800ACA88 8F392A84 */ lw $t9, %lo(D_800E2A84)($t9) +/* 0AD684 800ACA84 3C19800E */ lui $t9, %hi(gLensFlareOff) # $t9, 0x800e +/* 0AD688 800ACA88 8F392A84 */ lw $t9, %lo(gLensFlareOff)($t9) /* 0AD68C 800ACA8C 00000000 */ nop /* 0AD690 800ACA90 17200122 */ bnez $t9, .L800ACF1C /* 0AD694 800ACA94 8FBF005C */ lw $ra, 0x5c($sp) @@ -46,8 +46,8 @@ glabel func_800ACA20 /* 0AD6D0 800ACAD0 00A03025 */ move $a2, $a1 /* 0AD6D4 800ACAD4 0C01BDBB */ jal f32_matrix_dot /* 0AD6D8 800ACAD8 00402025 */ move $a0, $v0 -/* 0AD6DC 800ACADC 3C1E8012 */ lui $fp, %hi(D_80127C30) # $fp, 0x8012 -/* 0AD6E0 800ACAE0 27DE7C30 */ addiu $fp, %lo(D_80127C30) # addiu $fp, $fp, 0x7c30 +/* 0AD6DC 800ACADC 3C1E8012 */ lui $fp, %hi(gLensFlarePos) # $fp, 0x8012 +/* 0AD6E0 800ACAE0 27DE7C30 */ addiu $fp, %lo(gLensFlarePos) # addiu $fp, $fp, 0x7c30 /* 0AD6E4 800ACAE4 C7C60000 */ lwc1 $f6, ($fp) /* 0AD6E8 800ACAE8 C7A400D8 */ lwc1 $f4, 0xd8($sp) /* 0AD6EC 800ACAEC C7CA0004 */ lwc1 $f10, 4($fp) @@ -118,19 +118,19 @@ glabel func_800ACA20 /* 0AD7F0 800ACBF0 E7A600E0 */ swc1 $f6, 0xe0($sp) .L800ACBF4: /* 0AD7F4 800ACBF4 16400004 */ bnez $s2, .L800ACC08 -/* 0AD7F8 800ACBF8 3C108012 */ lui $s0, %hi(D_80127C2C) # $s0, 0x8012 -/* 0AD7FC 800ACBFC 8E107C2C */ lw $s0, %lo(D_80127C2C)($s0) +/* 0AD7F8 800ACBF8 3C108012 */ lui $s0, %hi(gLensFlareLarge) # $s0, 0x8012 +/* 0AD7FC 800ACBFC 8E107C2C */ lw $s0, %lo(gLensFlareLarge)($s0) /* 0AD800 800ACC00 10000009 */ b .L800ACC28 /* 0AD804 800ACC04 00000000 */ nop .L800ACC08: /* 0AD808 800ACC08 16420005 */ bne $s2, $v0, .L800ACC20 -/* 0AD80C 800ACC0C 3C108012 */ lui $s0, %hi(D_80127C28) # $s0, 0x8012 -/* 0AD810 800ACC10 3C108012 */ lui $s0, %hi(D_80127C24) # $s0, 0x8012 -/* 0AD814 800ACC14 8E107C24 */ lw $s0, %lo(D_80127C24)($s0) +/* 0AD80C 800ACC0C 3C108012 */ lui $s0, %hi(gLensFlareSet2) # $s0, 0x8012 +/* 0AD810 800ACC10 3C108012 */ lui $s0, %hi(gLensFlareSet1) # $s0, 0x8012 +/* 0AD814 800ACC14 8E107C24 */ lw $s0, %lo(gLensFlareSet1)($s0) /* 0AD818 800ACC18 10000003 */ b .L800ACC28 /* 0AD81C 800ACC1C 00000000 */ nop .L800ACC20: -/* 0AD820 800ACC20 8E107C28 */ lw $s0, %lo(D_80127C28)($s0) +/* 0AD820 800ACC20 8E107C28 */ lw $s0, %lo(gLensFlareSet2)($s0) /* 0AD824 800ACC24 00000000 */ nop .L800ACC28: /* 0AD828 800ACC28 12000058 */ beqz $s0, .L800ACD8C @@ -261,8 +261,8 @@ glabel func_800ACA20 /* 0ADA08 800ACE08 8E230000 */ lw $v1, ($s1) /* 0ADA0C 800ACE0C 8FAA0098 */ lw $t2, 0x98($sp) /* 0ADA10 800ACE10 00602025 */ move $a0, $v1 -/* 0ADA14 800ACE14 3C0C800E */ lui $t4, %hi(D_800E2928) # $t4, 0x800e -/* 0ADA18 800ACE18 258C2928 */ addiu $t4, %lo(D_800E2928) # addiu $t4, $t4, 0x2928 +/* 0ADA14 800ACE14 3C0C800E */ lui $t4, %hi(dLensFlare) # $t4, 0x800e +/* 0ADA18 800ACE18 258C2928 */ addiu $t4, %lo(dLensFlare) # addiu $t4, $t4, 0x2928 /* 0ADA1C 800ACE1C 3C190600 */ lui $t9, 0x600 /* 0ADA20 800ACE20 24630008 */ addiu $v1, $v1, 8 /* 0ADA24 800ACE24 00024403 */ sra $t0, $v0, 0x10 diff --git a/extract-ver/us_1.0.config.json b/extract-ver/us_1.0.config.json index 62f41664..e5e75964 100644 --- a/extract-ver/us_1.0.config.json +++ b/extract-ver/us_1.0.config.json @@ -15403,6 +15403,11 @@ "misc-type": "RacerStat", "folder": "racer_stats" }, + { + "index": 12, + "filename": "balloon_data", + "build-id": "ASSET_MISC_BALLOON_DATA" + }, { "index": 19, "filename": "rumble_data", @@ -15418,6 +15423,11 @@ "filename": "magnet_data", "build-id": "ASSET_MISC_MAGNET_DATA" }, + { + "index": 24, + "filename": "ghost_unlock_times", + "build-id": "ASSET_MISC_GHOST_UNLOCK_TIMES" + }, { "index": 26, "filename": "tracks_menu_ids", @@ -20413,7 +20423,7 @@ "LevelObjectEntry_Trigger", "LevelObjectEntryCommon", "LevelObjectEntry_AirZippers_WaterZippers", - "LevelObjectEntry_Unknown58", + "LevelObjectEntry_TimeTrial_Ghost", "LevelObjectEntry_WaveGenerator", "LevelObjectEntry_WavePower", "LevelObjectEntry_Butterfly", diff --git a/include/asset_enums.h b/include/asset_enums.h index 2851048f..b173173c 100644 --- a/include/asset_enums.h +++ b/include/asset_enums.h @@ -3061,7 +3061,7 @@ typedef enum AssetMiscEnum { ASSET_MISC_RACER_WEIGHT, ASSET_MISC_RACER_HANDLING, ASSET_MISC_RACER_UNUSED_11, - ASSET_MISC_12, + ASSET_MISC_BALLOON_DATA, ASSET_MISC_13, ASSET_MISC_14, ASSET_MISC_15, @@ -3073,7 +3073,7 @@ typedef enum AssetMiscEnum { ASSET_MISC_SHIELD_DATA, ASSET_MISC_MAGNET_DATA, ASSET_MISC_23, - ASSET_MISC_24, + ASSET_MISC_GHOST_UNLOCK_TIMES, ASSET_MISC_25, ASSET_MISC_TRACKS_MENU_IDS, ASSET_MISC_HUB_AREA_IDS, diff --git a/include/level_object_entries.h b/include/level_object_entries.h index 3817846d..5c1a91b1 100644 --- a/include/level_object_entries.h +++ b/include/level_object_entries.h @@ -112,14 +112,14 @@ typedef struct LevelObjectEntry_AudioLine { typedef struct LevelObjectEntry_CameraControl { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ s8 unk8; + /* 0x08 */ s8 cameraID; /* 0x09 */ s8 pad9; } LevelObjectEntry_CameraControl; typedef struct LevelObjectEntry_SetupPoint { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; + /* 0x08 */ u8 racerIndex; + /* 0x09 */ u8 entranceID; /* 0x0A */ u8 angleY; Hint((Angle, DivideBy:64)) /* 0x0B */ s8 vehicle; Hint((Enum:Vehicle)) } LevelObjectEntry_SetupPoint; @@ -158,16 +158,16 @@ typedef struct LevelObjectEntry_Door { /* 0x09 */ u8 openRotation; Hint((Angle, DivideBy:64)) /* 0x0A */ u8 modelIndex; /* 0x0B */ u8 distanceToOpen; - /* 0x0C */ s8 unkC; - /* 0x0D */ u8 numBalloonsToOpen; - /* 0x0E */ u8 unkE; - /* 0x0F */ u8 unkF; + /* 0x0C */ s8 doorID; + /* 0x0D */ u8 balloonCount; + /* 0x0E */ u8 doorType; + /* 0x0F */ u8 textID; /* 0x10 */ u8 unk10; - /* 0x11 */ s8 unk11; + /* 0x11 */ s8 keyID; /* 0x12 */ u8 scale; - /* 0x13 */ s8 unk13; - /* 0x14 */ s8 unk14; - /* 0x15 */ u8 unk15; + /* 0x13 */ s8 localBalloons; // Use world balloon count instead of total. + /* 0x14 */ s8 levelID; + /* 0x15 */ u8 balloonCountOverride; // Secondary balloon count requirement, for Future Fun Land. } LevelObjectEntry_Door; typedef struct LevelObjectEntry_FogChanger { @@ -184,9 +184,9 @@ typedef struct LevelObjectEntry_FogChanger { typedef struct LevelObjectEntry_AiNode { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; - /* 0x0A */ u8 unkA[4]; - /* 0x0E */ s8 unkE; + /* 0x09 */ u8 nodeID; + /* 0x0A */ u8 adjacent[4]; + /* 0x0E */ s8 elevation; /* 0x0F */ s8 padF; } LevelObjectEntry_AiNode; @@ -194,7 +194,7 @@ typedef struct LevelObjectEntry_WeaponBalloon { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 unk8; // Unused? /* 0x09 */ u8 balloonType; Hint((Enum:BalloonType)) - /* 0x0A */ u8 radius; Hint((Scale, DivideBy:64)) // This is divided by 64 to get actual scale. + /* 0x0A */ u8 scale; Hint((Scale, DivideBy:64)) // This is divided by 64 to get actual scale. /* 0x0B */ u8 padB; } LevelObjectEntry_WeaponBalloon; @@ -304,7 +304,7 @@ typedef struct LevelObjectEntry_Bridge_WhaleRamp { /* 0x0B */ u8 unkB; /* 0x0C */ u8 radius; /* 0x0D */ u8 unkD; - /* 0x0E */ s8 unkE; + /* 0x0E */ s8 bobAmount; // How far up and down the whale goes /* 0x0F */ u8 allowedVehicles; } LevelObjectEntry_Bridge_WhaleRamp; @@ -327,19 +327,18 @@ typedef struct LevelObjectEntry_Bonus { typedef struct LevelObjectEntry_LensFlare { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ s16 unk8; - /* 0x0A */ s16 unkA; - /* 0x0C */ u8 unkC; - /* 0x0D */ u8 unkD; - /* 0x0E */ u8 unkE; - /* 0x0F */ u8 unkF; - /* 0x10 */ u8 unk10[4]; + /* 0x08 */ s16 angleX; + /* 0x0A */ s16 angleY; + /* 0x0C */ u8 set1; + /* 0x0D */ u8 set2; + /* 0x0E */ u8 largeShine; + /* 0x0A */ u8 pad[5]; } LevelObjectEntry_LensFlare; typedef struct LevelObjectEntry_LensFlareSwitch { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ s16 radius; - /* 0x0A */ u8 unkA[10]; + /* 0x0A */ u8 pad[10]; } LevelObjectEntry_LensFlareSwitch; typedef struct LevelObjectEntry_CollectEgg { @@ -407,7 +406,7 @@ typedef struct LevelObjectEntry_Animation { typedef struct LevelObjectEntry_InfoPoint { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ u8 unk8[3]; + /* 0x08 */ u8 hitbox[3]; /* 0x0B */ u8 unkB; } LevelObjectEntry_InfoPoint; @@ -429,9 +428,9 @@ typedef struct LevelObjectEntry_AirZippers_WaterZippers { /* 0x0B */ u8 padB; } LevelObjectEntry_AirZippers_WaterZippers; -typedef struct LevelObjectEntry_Unknown58 { +typedef struct LevelObjectEntry_TimeTrial_Ghost { /* 0x00 */ LevelObjectEntryCommon common; -} LevelObjectEntry_Unknown58; +} LevelObjectEntry_TimeTrial_Ghost; typedef struct LevelObjectEntry_WaveGenerator { /* 0x00 */ LevelObjectEntryCommon common; @@ -534,7 +533,7 @@ typedef struct LevelObjectEntry_Bubbler { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 particlePropertyID; /* 0x09 */ u8 particleBehaviourID; - /* 0x0A */ u16 unkA; + /* 0x0A */ u16 particleDensity; /* 0x0C */ u8 unkC[4]; } LevelObjectEntry_Bubbler; @@ -632,8 +631,8 @@ typedef struct LevelObjectEntry_Windsail { typedef struct LevelObjectEntry_RangeTrigger { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ u16 unk8; - /* 0x0A */ u16 unkA; + /* 0x08 */ u16 radius; + /* 0x0A */ u16 particleFlags; } LevelObjectEntry_RangeTrigger; typedef struct LevelObjectEntry_Fireball_Octoweapon { @@ -655,11 +654,11 @@ typedef struct LevelObjectEntry_TTDoor { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 angleY; Hint((Angle, DivideBy:64)) // Rotation when closed /* 0x09 */ u8 unk9; Hint((Angle, DivideBy:64)) // Rotation when open - /* 0x0A */ u8 unkA; - /* 0x0B */ u8 unkB; - /* 0x0C */ u8 radius; + /* 0x0A */ u8 radius; + /* 0x0B */ u8 textID; + /* 0x0C */ u8 scale; /* 0x0D */ u8 padD; - /* 0x0E */ s8 doorID; + /* 0x0E */ s8 doorType; /* 0x0F */ s8 padF; } LevelObjectEntry_TTDoor; @@ -929,7 +928,7 @@ typedef struct LevelObjectEntry { LevelObjectEntry_InfoPoint infoPoint; LevelObjectEntry_Trigger trigger; LevelObjectEntry_AirZippers_WaterZippers airzipper_waterzipper; - LevelObjectEntry_Unknown58 unk58; + LevelObjectEntry_TimeTrial_Ghost ghost; LevelObjectEntry_WaveGenerator waverGenerator; LevelObjectEntry_Butterfly butterfly; LevelObjectEntry_Parkwarden taj; diff --git a/include/object_behaviors.h b/include/object_behaviors.h index fb0ab6e9..6712e74d 100644 --- a/include/object_behaviors.h +++ b/include/object_behaviors.h @@ -60,7 +60,7 @@ enum ObjectBehaviours { BHV_TRIGGER, BHV_VEHICLE_ANIMATION, BHV_ZIPPER_WATER, - BHV_UNK_3A, + BHV_TIMETRIAL_GHOST, BHV_WAVE_GENERATOR, BHV_WAVE_POWER, BHV_BUTTERFLY, diff --git a/include/object_properties.h b/include/object_properties.h index 7736e1b6..36e3785a 100644 --- a/include/object_properties.h +++ b/include/object_properties.h @@ -26,9 +26,9 @@ typedef struct ObjPropertySpeed { } ObjPropertySpeed; typedef struct ObjPropertyBanana { - s32 unk0; - s16 unk4; - s16 unk6; + s32 status; + s16 intangibleTimer; + s16 destroyTimer; } ObjPropertyBanana; typedef struct ObjPropertyName { @@ -141,7 +141,7 @@ typedef struct ObjPropertyWorldKey { typedef struct ObjPropertyWeaponBalloon { s32 balloonID; - s32 unk4; + s32 particleTimer; } ObjPropertyWeaponBalloon; typedef struct ObjPropertyRacer { @@ -150,17 +150,26 @@ typedef struct ObjPropertyRacer { } ObjPropertyRacer; typedef struct ObjPropertySetupPoint { - s32 unk0; - s32 unk4; + s32 racerIndex; + s32 entranceID; } ObjPropertySetupPoint; typedef struct ObjPropertyWeapon { - s32 unk0; - u8 unk4; - u8 unk5; - s16 unk6; + s32 decayTimer; + u8 status; + u8 submerged; + s16 scale; } ObjPropertyWeapon; +typedef struct ObjPropertyCamControl { + s32 cameraID; +} ObjPropertyCamControl; + +typedef struct ObjPropertyTimeTrial { + s32 timestamp; + struct ObjectHeader *header; +} ObjPropertyTimeTrial; + typedef struct ObjProperties { union { ObjPropertyCommon common; @@ -193,6 +202,8 @@ typedef struct ObjProperties { ObjPropertyRacer racer; ObjPropertySetupPoint setupPoint; ObjPropertyWeapon weapon; + ObjPropertyCamControl camControl; + ObjPropertyTimeTrial timeTrial; }; } ObjProperties; diff --git a/include/structs.h b/include/structs.h index 6b2a637e..2dd98553 100644 --- a/include/structs.h +++ b/include/structs.h @@ -773,7 +773,7 @@ typedef struct ObjectHeader { /* 0x54 */ s8 behaviorId; /* 0x55 */ s8 numberOfModelIds; // size of array pointed by Object->unk68 /* 0x56 */ s8 unk56; - /* 0x57 */ s8 unk57; + /* 0x57 */ s8 particleCount; // Number of different particle types that are attached /* 0x58 */ s8 unk58; /* 0x59 */ u8 pad59; /* 0x5A */ s8 numLightSources; @@ -943,18 +943,18 @@ typedef struct Object_Animation { /* 0x24 */ s16 unk24; /* 0x26 */ s16 unk26; /* 0x28 */ u16 unk28; - /* 0x2A */ u16 unk2A; + /* 0x2A */ u16 startDelay; /* 0x2C */ u8 unk2C; /* 0x2D */ u8 unk2D; /* 0x2E */ u8 unk2E; /* 0x2F */ u8 unk2F; - /* 0x30 */ s8 unk30; + /* 0x30 */ s8 cameraID; /* 0x31 */ u8 unk31; /* 0x32 */ u8 unk32; /* 0x33 */ u8 unk33; /* 0x34 */ u8 unk34; /* 0x35 */ u8 unk35; - /* 0x36 */ s16 unk36; + /* 0x36 */ s16 pauseCounter; /* 0x38 */ u8 unk38; /* 0x39 */ u8 unk39; /* 0x3A */ u8 unk3A; @@ -983,8 +983,8 @@ typedef struct Object_OverridePos { } Object_OverridePos; typedef struct Object_WeaponBalloon { - /* 0x0 */ f32 radius; - /* 0x4 */ s16 unk4; + /* 0x0 */ f32 scale; + /* 0x4 */ s16 respawnTime; /* 0x6 */ s8 unk6[0x2]; } Object_WeaponBalloon; @@ -1074,7 +1074,7 @@ typedef struct Object_CharacterFlag { typedef struct Object_AnimCamera { /* 0x00 */ u8 pad0[0x30]; - /* 0x30 */ s8 unk30; + /* 0x30 */ s8 cameraID; /* 0x31 */ u8 pad31[0xB]; /* 0x3C */ s32 unk3C; /* 0x40 */ u8 pad40[4]; @@ -1089,19 +1089,6 @@ typedef struct Object_InfoPoint { /* 0x0 */ s16 unk0; } Object_InfoPoint; -typedef struct Object_TTDoor { - /* 0x00 */ f32 homeY; - /* 0x04 */ SoundMask *soundMask; - /* 0x08 */ s32 unk8; - /* 0x0C */ s16 unkC; - /* 0x0C */ s8 unkE; - /* 0x0F */ u8 doorID; - /* 0x10 */ u8 pad10[2]; - /* 0x12 */ u8 unk12; - /* 0x13 */ s8 unk13; - /* 0x14 */ s32 unk14; -} Object_TTDoor; - typedef struct Object_WorldKey { /* 0x0 */ s16 unk0; } Object_WorldKey; @@ -1187,13 +1174,13 @@ typedef struct Object_Exit { typedef struct Object_AiNode { /* 0x00 */ struct Object *nodeObj[4]; /* 0x10 */ s16 distToNode[4]; - /* 0x18 */ u8 unk18[4]; + /* 0x18 */ s8 directions[4]; } Object_AiNode; /* Size: 0x224 - 548 bytes */ typedef struct Object_Racer { /* 0x000 */ s16 playerIndex; // -1 = AI Controlled, 0 to 3 = Object controlled - /* 0x002 */ s8 unk2; + /* 0x002 */ s8 racerIndex; // Unique ID for each racer object. /* 0x003 */ s8 characterId; // Affects minimap color, horn, voice, etc. /* 0x004 */ s32 unk4; /* 0x008 */ f32 forwardVel; @@ -1261,7 +1248,7 @@ typedef struct Object_Racer { /* 0x11C */ f32 unk11C; /* 0x120 */ f32 unk120; /* 0x124 */ f32 unk124; - /* 0x128 */ s32 lap_times[5]; //func_80022948 implies there should be at least 5 lap times. + /* 0x128 */ s32 lap_times[5]; //mode_init_taj_race implies there should be at least 5 lap times. /* 0x13C */ s32 unk13C; /* 0x140 */ struct Object *magnetTargetObj; /* 0x144 */ struct Object *held_obj; @@ -1269,8 +1256,8 @@ typedef struct Object_Racer { /* 0x14C */ struct Object *zipperObj; /* 0x150 */ struct Object *unk150; /* 0x154 */ struct Object *unk154; - /* 0x158 */ struct Object *unk158; - /* 0x15C */ struct Object *unk15C; + /* 0x158 */ struct Object *nodeCurrent; + /* 0x15C */ struct Object *challengeMarker; /* 0x160 */ s16 y_rotation_offset; /* 0x162 */ s16 x_rotation_offset; /* 0x164 */ s16 z_rotation_offset; @@ -1394,7 +1381,7 @@ typedef struct Object_Racer { /* 0x20E */ u16 delaySoundID; /* 0x210 */ u8 delaySoundTimer; /* 0x211 */ s8 unk211; - /* 0x212 */ s8 unk212; + /* 0x212 */ s8 elevation; // Some maps like Icicle Pyramid have elevation levels that are communicated on the minimap. /* 0x213 */ s8 unk213; /* 0x214 */ s8 unk214; /* 0x215 */ s8 unk215; @@ -1407,16 +1394,17 @@ typedef struct Object_Racer { typedef struct Object_Door { /* 0x00 */ f32 homeY; - /* 0x04 */ SoundMask *unk4; - /* 0x08 */ s32 unk8; - /* 0x0A */ s16 unkA; - /* 0x0E */ s8 unkE; - /* 0x0F */ u8 unkF; - /* 0x10 */ u8 unk10; - /* 0x11 */ u8 unk11; - /* 0x12 */ u8 unk12; - /* 0x13 */ s8 unk13; - /* 0x14 */ s8 unk14[4]; + /* 0x04 */ SoundMask *soundMask; + /* 0x08 */ s32 jingleTimer; + /* 0x0A */ s16 jingleCooldown; + /* 0x0E */ s8 doorID; + /* 0x0F */ u8 doorType; + /* 0x10 */ u8 balloonCount; + /* 0x11 */ u8 balloonCountUnused; + /* 0x12 */ u8 radius; + /* 0x13 */ s8 textID; + /* 0x14 */ s8 keyID; + /* 0x15 */ s8 openDir; } Object_Door; typedef struct Object_Trigger { @@ -1481,7 +1469,7 @@ typedef struct Object_Banana { /* 0x0 */ s32 unk0; /* 0x4 */ struct Object *spawner; /* 0x8 */ s8 unk8; - /* 0x9 */ s8 unk9; + /* 0x9 */ s8 droppedVehicleID; } Object_Banana; typedef struct Object_FogChanger { @@ -1492,11 +1480,11 @@ typedef struct Object_NPC { /* 0x00 */ f32 unk0; /* 0x04 */ f32 animFrameF; /* 0x08 */ s32 unk8; - /* 0x0C */ s8 unkC; - /* 0x0D */ u8 unkD; - /* 0x0E */ u8 unkE; - /* 0x0F */ u8 unkF; - /* 0x10 */ u8 unk10; + /* 0x0C */ s8 nodeBack1; // One node backwards + /* 0x0D */ u8 nodeCurrent; // Intended target node + /* 0x0E */ u8 nodeBack2; // Two nodes backward + /* 0x0F */ u8 nodeForward1; // One node forward + /* 0x10 */ u8 nodeForward2; // Two nodes forward /* 0x11 */ u8 fogR; /* 0x12 */ u8 fogG; /* 0x13 */ u8 fogB; @@ -1522,8 +1510,8 @@ typedef struct Object_TT { } Object_TT; typedef struct Object_Bridge_WhaleRamp { - /* 0x0 */ f32 unk0; - /* 0x4 */ SoundMask *unk4; + /* 0x0 */ f32 homeY; + /* 0x4 */ SoundMask *soundMask; } Object_Bridge_WhaleRamp; typedef struct Object_8001B7A8 { @@ -1561,12 +1549,12 @@ typedef struct Object_Fireball_Octoweapon { typedef struct Object_AnimatedObject { u8 pad0[0x20]; /* 0x20 */ u32 soundMask; - /* 0x24 */ s16 unk24; + /* 0x24 */ s16 currentSound; /* 0x26 */ s16 unk26; s16 unk28; u8 pad2A[0xC]; s16 unk36; - s8 unk38; + s8 soundID; s8 unk39; s8 unk3A; s8 unk3B; @@ -1638,7 +1626,6 @@ typedef struct Object_64 { Object_CharacterFlag character_flag; Object_AnimCamera anim_camera; Object_InfoPoint info_point; - Object_TTDoor tt_door; Object_WorldKey world_key; Object_AudioLine audio_line; Object_AudioReverb audio_reverb; @@ -1707,7 +1694,7 @@ typedef struct Object_68 { } Object_68; /* Size: 0x20 bytes */ -typedef struct Object_6C { +typedef struct ParticleEmitter { /* 0x00 */ struct Particle *unk0; /* 0x04 */ s16 unk4; /* 0x06 */ u8 unk6; @@ -1715,7 +1702,7 @@ typedef struct Object_6C { /* 0x08 */ s16 unk8; /* 0x0A */ s16 unkA; /* 0x0C */ u8 padC[0x14]; -} Object_6C; +} ParticleEmitter; /* Size: 0xA0 bytes */ typedef struct ParticleBehavior { @@ -1907,9 +1894,9 @@ typedef struct Object { /* 0x0060 */ Object_60 *unk60; //player + 0x340 /* 0x0064 */ Object_64 *unk64; //player + 0x98 /* 0x0068 */ Object_68 **unk68; //player + 0x80 - /* 0x006C */ Object_6C *unk6C; //player + 0x370 + /* 0x006C */ ParticleEmitter *particleEmitter; //player + 0x370 /* 0x0070 */ Object_LightData **lightData; - /* 0x0074 */ u32 unk74; + /* 0x0074 */ u32 particleEmitFlags; /* 0x0078 */ ObjProperties properties; /* 0x0080 */ void *unk80; /* 0x0084 */ u32 unk84; @@ -1959,11 +1946,6 @@ typedef struct GhostNode { /* 0x0A */ s16 yRotation; } GhostNode; -/* Size: 12 bytes */ -typedef struct GhostDataFrame { - u8 pad0[12]; -} GhostDataFrame; - typedef struct ByteColour { u8 red; u8 green; diff --git a/src/audio_spatial.c b/src/audio_spatial.c index 110a6d05..c3e65cc7 100644 --- a/src/audio_spatial.c +++ b/src/audio_spatial.c @@ -37,7 +37,7 @@ UNUSED const char D_800E4EDC[] = "Reverb line definition error (line=%d, vertex= /************ .bss ************/ -extern s8 D_8011AC18; +extern s8 gAudioLinesOff; extern SoundData *D_80119C40; extern unk80119C58 D_80119C58[]; extern unk8011A6D8 D_8011A6D8[]; @@ -69,13 +69,19 @@ void func_80008040(void) { GLOBAL_ASM("asm/non_matchings/audio_spatial/func_80008040.s") #endif -void func_80008140(void) { +/** + * Stop any playing jingles, then block audio lines from playing anymore. + */ +void audioline_off(void) { music_jingle_stop(); - D_8011AC18 = 1; + gAudioLinesOff = TRUE; } -void func_80008168(void) { - D_8011AC18 = 0; +/** + * Allow audio lines to play jingles. + */ +void audioline_on(void) { + gAudioLinesOff = FALSE; } #ifdef NON_EQUIVALENT @@ -95,7 +101,7 @@ void func_80008174(void) { for (i = 0; i < gUsedMasks; i++) { gSoundMaskHeapUsed[i]->unk12 = 0; if (gSoundMaskHeapUsed[i]->unk18 != NULL) { - func_8000488C(gSoundMaskHeapUsed[i]->unk18); + sound_stop(gSoundMaskHeapUsed[i]->unk18); } } gUsedMasks = 0; @@ -104,7 +110,7 @@ void func_80008174(void) { D_80119C58[i].soundID = 0; if (D_80119C58[i].unk178 != 0) { if (D_80119C58[i].unk0.unk0_02 == 0) { - func_8000488C(D_80119C58[i].unk178); + sound_stop(D_80119C58[i].unk178); } else if (D_80119C58[i].unk0.unk0_02 == 1) { music_jingle_stop(); } @@ -126,7 +132,7 @@ void func_80008174(void) { // } } - D_8011AC18 = 0; + gAudioLinesOff = 0; } #else GLOBAL_ASM("asm/non_matchings/audio_spatial/func_80008174.s") @@ -463,7 +469,7 @@ GLOBAL_ASM("asm/non_matchings/audio_spatial/func_8000A184.s") void func_8000A2E8(s32 arg0) { if (gUsedMasks != 0) { if (gSoundMaskHeapUsed[arg0]->unk18 != 0) { - func_8000488C(gSoundMaskHeapUsed[arg0]->unk18); + sound_stop(gSoundMaskHeapUsed[arg0]->unk18); } if (gSoundMaskHeapUsed[arg0]->soundMask != NULL) { *gSoundMaskHeapUsed[arg0]->soundMask = NULL; diff --git a/src/audio_spatial.h b/src/audio_spatial.h index 76489e6c..e885214b 100644 --- a/src/audio_spatial.h +++ b/src/audio_spatial.h @@ -50,15 +50,15 @@ typedef struct unk800A414_arg3 { f32 unk14; } unk800A414_arg3; -void func_80008168(void); +void audioline_on(void); void func_800096F8(SoundMask *); -void func_80008140(void); +void audioline_off(void); void func_8000974C(u16 soundBite, f32 x, f32 y, f32 z, u8 arg4, u8 arg5, u8 volume, u16 distance, u8 arg8, u8 pitch, u8 argA, SoundMask **soundMask); void play_sound_at_position(u16 soundId, f32 x, f32 y, f32 z, u8 arg4, SoundMask **soundMask); void func_8000A2E8(s32 arg0); s32 func_800090C0(f32, f32, s32); -void func_800095E8(u16 soundId, f32 x, f32 y, f32 z, u8 arg4, u8 arg5, f32 arg6, SoundMask **soundMask); +void func_800095E8(u16 soundId, f32 x, f32 y, f32 z, u8 arg4, u8 arg5, f32 pitch, SoundMask **soundMask); void audioline_ambient_create(u8 arg0, u16 soundId, f32 x, f32 y, f32 z, u8 arg5, u8 arg6, u8 arg7, u8 arg8, u16 arg9, u8 argA, u8 lineID, u8 argC); s32 func_800099EC(u8 arg0); diff --git a/src/audio_vehicle.c b/src/audio_vehicle.c index f1f93a8e..718fce72 100644 --- a/src/audio_vehicle.c +++ b/src/audio_vehicle.c @@ -40,7 +40,7 @@ f32 D_80119C60[670]; // array size of 672 looks to be required for func_800 unk8011A6D8 *D_8011A6D8; // unk8011A6D8[] | Reverb stuff unk8011A6D8 **D_8011A6DC; // Struct of size 0xC0 f32 D_8011A6E0[334]; -s32 D_8011AC18; +s32 gAudioLinesOff; s32 D_8011AC1C; /******************************/ @@ -327,7 +327,7 @@ void func_80005254(Object *obj, u32 buttonsPressed, u32 buttonsHeld, s32 updateR if (((gSoundRacerObj->unk10 != 0) || (gSoundRacerObj->unk14 != 0) || !(buttonsHeld & B_BUTTON) || (gSoundRacerObj->velocity > -0.1) || (gSoundRacerObj->vehicleID == 4)) && (gRacerSound->unkA8 != 0)) { - func_8000488C(gRacerSound->unkA8); + sound_stop(gRacerSound->unkA8); gRacerSound->unkA8 = 0; } else if ((buttonsPressed & B_BUTTON) && (gRacerSound->unkA8 == 0) && (gSoundRacerObj->playerIndex >= 0)) { if (gSoundRacerObj->velocity < 0.0f) { @@ -566,7 +566,7 @@ void func_800063EC(Object *obj, UNUSED u32 buttonsPressed, u32 buttonsHeld, s32 } else if (gSoundRacerObj->spinout_timer == 0) { gRacerSound->brakeSound = FALSE; if (gRacerSound->brakeSoundMask != NULL) { - func_8000488C(gRacerSound->brakeSoundMask); + sound_stop(gRacerSound->brakeSoundMask); } } } @@ -584,16 +584,16 @@ void racer_sound_free(Object *obj) { if (gRacerSound != NULL) { for (i = 0; i != 2; i++) { if (gRacerSound->unk48[i] != NULL) { - func_8000488C(gRacerSound->unk48[i]); + sound_stop(gRacerSound->unk48[i]); gRacerSound->unk48[i] = 0; } } if (gRacerSound->unk50 != NULL) { - func_8000488C(gRacerSound->unk50); + sound_stop(gRacerSound->unk50); gRacerSound->unk50 = NULL; } if (gRacerSound->unkA8 != NULL) { - func_8000488C(gRacerSound->unkA8); + sound_stop(gRacerSound->unkA8); gRacerSound->unkA8 = 0; } for (i = 0; i < ARRAY_COUNT(D_80119C30); i++) { @@ -754,11 +754,11 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 sound_event_update(gRacerSound->unk50, 4, gRacerSound->unk91[0]); } } else if (gRacerSound->unk50 != NULL) { - func_8000488C(gRacerSound->unk50); + sound_stop(gRacerSound->unk50); gRacerSound->unk50 = 0; } } else if (gRacerSound->unk50 != NULL) { - func_8000488C(gRacerSound->unk50); + sound_stop(gRacerSound->unk50); gRacerSound->unk50 = 0; } for (loopCount2 = 0; loopCount2 < 2 && gRacerSound->unk0[loopCount2] != 0 && var_f26 != 0.0; loopCount2++) { @@ -770,12 +770,12 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 } if ((loopCount2 == 0) && (gRacerSound->unk44[0] & 1)) { if (gRacerSound->unk48[0] != NULL) { - func_8000488C(gRacerSound->unk48[0]); + sound_stop(gRacerSound->unk48[0]); gRacerSound->unk48[0] = NULL; } } else { if ((gRacerSound->unk48[loopCount2] != NULL) && (temp_s3 == 0)) { - func_8000488C(gRacerSound->unk48[loopCount2]); + sound_stop(gRacerSound->unk48[loopCount2]); gRacerSound->unk48[loopCount2] = NULL; } else { if (gRacerSound->unk48[loopCount2] == NULL) { @@ -860,7 +860,7 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 for (loopCount3 = 0; loopCount3 < ARRAY_COUNT(D_80119C30); loopCount3++) { if (D_80119C30[loopCount3] != NULL) { if (D_80119C30[loopCount3]->unk48[0] != NULL && D_80119C30[loopCount3]->unk88 < 8) { - func_8000488C(D_80119C30[loopCount3]->unk48[0]); + sound_stop(D_80119C30[loopCount3]->unk48[0]); D_80119C30[loopCount3]->unk48[0] = NULL; D_80119C30[loopCount3]->unk74 = 0; D_80119C30[loopCount3] = NULL; @@ -897,7 +897,7 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 gRacerSound->unk74 = 2; if (D_80119C30[loopCount3] != NULL) { if (D_80119C30[loopCount3]->unk48[0] != NULL) { - func_8000488C(D_80119C30[loopCount3]->unk48[0]); + sound_stop(D_80119C30[loopCount3]->unk48[0]); D_80119C30[loopCount3]->unk48[0] = NULL; gRacerSound->unk74 = 1; } diff --git a/src/audiomgr.c b/src/audiomgr.c index cf3beebd..cc058717 100644 --- a/src/audiomgr.c +++ b/src/audiomgr.c @@ -171,7 +171,7 @@ void amCreateAudioMgr(ALSynConfig *c, OSPri pri, OSSched *audSched) { } /* last buffer already linked, but still needs buffer */ dmaBuffs[i].ptr = alHeapAlloc(c->heap, 1, DMA_BUFFER_LENGTH); - +#ifdef ANTI_TAMPER // Antipiracy measure gAntiPiracyCRCStart = DMA_BUFFER_LENGTH; checksum = (s32) &func_80019808 - gAntiPiracyCRCStart; @@ -186,6 +186,7 @@ void amCreateAudioMgr(ALSynConfig *c, OSPri pri, OSSched *audSched) { if (checksum != gFunc80019808Checksum) { gAntiPiracyAudioFreq = TRUE; } +#endif for (i = 0; i < NUM_ACMD_LISTS; i++) { __am.ACMDList[i] = (Acmd *) alHeapAlloc(c->heap, 1, 0xA000); // sizeof(Acmd) * DMA_BUFFER_LENGTH * 5? @@ -302,11 +303,12 @@ static u32 __amHandleFrameMsg(AudioInfo *info, AudioInfo *lastInfo) { gLastAudioPtr = outputDataPointer = lastInfo->data; gLastAudioFrameSamples = frameSamples = lastInfo->frameSamples << 2; osAiSetNextBuffer(outputDataPointer, frameSamples); - +#ifdef ANTI_TAMPER // Antipiracy measure - if (gAntiPiracyAudioFreq != 0) { + if (gAntiPiracyAudioFreq) { osAiSetFrequency(get_random_number_from_range(0, 10000) + OUTPUT_RATE); } +#endif } /* calculate how many samples needed for this frame to keep the DAC full */ diff --git a/src/audiosfx.c b/src/audiosfx.c index ba6e8681..e8e8a5f0 100644 --- a/src/audiosfx.c +++ b/src/audiosfx.c @@ -231,7 +231,7 @@ GLOBAL_ASM("asm/non_matchings/audiosfx/func_80004668.s") // input typing not right (some type of struct) // 99% sure this function will clear the audio buffer associated with a given sound mask. -void func_8000488C(u8 *arg0) { +void sound_stop(u8 *arg0) { ALEvent sp_18; sp_18.type = 1024; //((u32 *)(&sp_18))[1] = (u32)arg0; diff --git a/src/audiosfx.h b/src/audiosfx.h index dca5b5e9..97f5f916 100644 --- a/src/audiosfx.h +++ b/src/audiosfx.h @@ -152,11 +152,11 @@ u16 get_sound_channel_volume(u8 channel); void set_sound_channel_volume(u8 channel, u16 volume); void func_8000418C(ALVoiceState *voiceState); void func_800048D8(u8 event); +INCONSISTENT void sound_stop(); // Non Matching void func_80004520(ALSoundState *); s32 func_80004668(ALBank *bnk, s16 sndIndx, u8, SoundMask *soundMask); -INCONSISTENT void func_8000488C(); void _handleEvent(unk800DC6BC *sndp, ALSndpEvent *event); #endif diff --git a/src/borders.c b/src/borders.c index b73f56ed..55beef8b 100644 --- a/src/borders.c +++ b/src/borders.c @@ -17,7 +17,7 @@ * 2 player has a single horizontal line, while 3 and 4 player splits the screen into quadrants. * 3 player will completely fill in where player 4 would normally be. */ -void render_borders_for_multiplayer(Gfx **dlist) { +void divider_draw(Gfx **dList) { u32 widthAndHeight, width, height; u32 y, x, xOffset, yOffset; LevelHeader *levelHeader; @@ -28,37 +28,36 @@ void render_borders_for_multiplayer(Gfx **dlist) { xOffset = width / 256; width += 0; // Fake match? yOffset = height / 128; - gDPSetCycleType((*dlist)++, G_CYC_FILL); - gDPSetFillColor((*dlist)++, GPACK_RGBA5551(0, 0, 0, 1) << 16 | GPACK_RGBA5551(0, 0, 0, 1)); // Black fill color + gDPSetCycleType((*dList)++, G_CYC_FILL); + gDPSetFillColor((*dList)++, GPACK_RGBA5551(0, 0, 0, 1) << 16 | GPACK_RGBA5551(0, 0, 0, 1)); // Black fill color switch (get_viewport_count()) { case VIEWPORTS_COUNT_2_PLAYERS: // Draws a solid horizontal black line in the middle of the screen. y = (height >> 1) - yOffset; - gDPFillRectangle((*dlist)++, height * 0, y, width, y + yOffset); + gDPFillRectangle((*dList)++, height * 0, y, width, y + yOffset); break; case VIEWPORTS_COUNT_3_PLAYERS: levelHeader = get_current_level_header(); // Draw black square in the bottom-right corner. if (get_hud_setting() || (levelHeader->race_type & RACETYPE_CHALLENGE)) { - gDPFillRectangle((*dlist)++, width >> 1, height >> 1, width, height); + gDPFillRectangle((*dList)++, width >> 1, height >> 1, width, height); } // There is no break statement here. This is intentional. case VIEWPORTS_COUNT_4_PLAYERS: x = (width >> 1) - xOffset; // Draws 2 black lines in the middle of the screen. One vertical, another horizontal. - gDPFillRectangle((*dlist)++, height * 0, (height >> 1) - yOffset, width, + gDPFillRectangle((*dList)++, height * 0, (height >> 1) - yOffset, width, ((height >> 1) - yOffset) + yOffset); - gDPFillRectangle((*dlist)++, x, 0, x + xOffset, height); + gDPFillRectangle((*dList)++, x, 0, x + xOffset, height); break; } } /** - * Appears to be largely the same as the function above, rendering after the UI. - * This instead, renders slightly larger (around 1px) borders that are invisible. - * The purpose of this function is unknown, because it has zero cosmetic effect. + * Draws the multiplayer borders again, but fully invisible using the XLU render mode. + * The effect here is that it will strip coverage for anything beneath, eliminating pixel bleed. */ -void render_second_multiplayer_borders(Gfx **dlist) { +void divider_clear_coverage(Gfx **dList) { u32 screenSize; u32 screenWidth; u32 screenHeight; @@ -72,22 +71,22 @@ void render_second_multiplayer_borders(Gfx **dlist) { screenWidth = GET_VIDEO_WIDTH(screenSize); height = (screenHeight / 128) << 1 << 1; width = (screenWidth / 256) << 1 << 1; - gDPSetCycleType((*dlist)++, G_CYC_1CYCLE); - gDPSetCombineMode((*dlist)++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); - gDPSetRenderMode((*dlist)++, G_RM_XLU_SURF, G_RM_XLU_SURF2); - gDPSetPrimColor((*dlist)++, 0, 0, 0, 0, 0, 0); + gDPSetCycleType((*dList)++, G_CYC_1CYCLE); + gDPSetCombineMode((*dList)++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); + gDPSetRenderMode((*dList)++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + gDPSetPrimColor((*dList)++, 0, 0, 0, 0, 0, 0); switch (get_viewport_count()) { case VIEWPORTS_COUNT_2_PLAYERS: tempY = (screenHeight / 2) - (height / 2); - gDPFillRectangle((*dlist)++, 0, tempY, screenWidth, tempY + height); + gDPFillRectangle((*dList)++, 0, tempY, screenWidth, tempY + height); break; case VIEWPORTS_COUNT_3_PLAYERS: case VIEWPORTS_COUNT_4_PLAYERS: tempY = (screenHeight / 2) - (height / 2); tempX = (screenWidth / 2) - (width / 2); - gDPFillRectangle((*dlist)++, 0, tempY, screenWidth, tempY + height); + gDPFillRectangle((*dList)++, 0, tempY, screenWidth, tempY + height); tempX += 0; // Fakematch - gDPFillRectangle((*dlist)++, tempX, 0, tempX + width, screenHeight); + gDPFillRectangle((*dList)++, tempX, 0, tempX + width, screenHeight); break; } } diff --git a/src/borders.h b/src/borders.h index d700f3c3..799904e5 100644 --- a/src/borders.h +++ b/src/borders.h @@ -4,7 +4,7 @@ #include "types.h" #include "f3ddkr.h" -void render_borders_for_multiplayer(Gfx **dlist); -void render_second_multiplayer_borders(Gfx **dlist); +void divider_draw(Gfx **dList); +void divider_clear_coverage(Gfx **dList); #endif diff --git a/src/camera.c b/src/camera.c index 461ffee9..6657f2ca 100644 --- a/src/camera.c +++ b/src/camera.c @@ -973,11 +973,13 @@ void func_8006807C(Gfx **dlist, MatrixS **mtx) { */ void viewport_rsp_set(Gfx **dlist, s32 width, s32 height, s32 posX, s32 posY) { s32 tempWidth = (get_filtered_cheats() & CHEAT_MIRRORED_TRACKS) ? -width : width; +#ifdef ANTI_TAMPER // Antipiracy measure. Flips the screen upside down. if (gAntiPiracyViewport) { height = -height; tempWidth = -width; } +#endif if (!(gScreenViewports[gActiveCameraID].flags & VIEWPORT_EXTRA_BG)) { gViewportStack[gActiveCameraID].vp.vtrans[0] = posX * 4; gViewportStack[gActiveCameraID].vp.vtrans[1] = posY * 4; diff --git a/src/game.c b/src/game.c index 676c9555..9466a07f 100644 --- a/src/game.c +++ b/src/game.c @@ -144,6 +144,7 @@ void init_level_globals(void) { } free_from_memory_pool(gTempAssetTable); // Antipiracy measure +#ifdef ANTI_TAMPER checksumCount = 0; for (j = 0; j < gViewportFuncLength; j++) { checksumCount += ((u8 *) (&viewport_rsp_set))[j]; @@ -151,6 +152,7 @@ void init_level_globals(void) { if (checksumCount != gViewportFuncChecksum) { disable_button_mask(); } +#endif } UNUSED s16 func_8006ABB4(s32 levelID) { @@ -569,7 +571,7 @@ void load_level(s32 levelId, s32 numberOfPlayers, s32 entranceId, Vehicle vehicl if (gCurrentLevelHeader->race_type == RACETYPE_DEFAULT && numPlayers == 0 && is_time_trial_enabled()) { cutsceneId = CUTSCENE_ID_UNK_64; } - set_cutscene_id(cutsceneId); + cutscene_id_set(cutsceneId); init_track(gCurrentLevelHeader->geometry, gCurrentLevelHeader->skybox, numberOfPlayers, vehicleId, entranceId, gCurrentLevelHeader->collectables, gCurrentLevelHeader->unkBA); if (gCurrentLevelHeader->fogNear == 0 && gCurrentLevelHeader->fogFar == 0 && gCurrentLevelHeader->fogR == 0 && diff --git a/src/game_text.c b/src/game_text.c index bd617d37..23cffcf6 100644 --- a/src/game_text.c +++ b/src/game_text.c @@ -326,12 +326,16 @@ void set_current_text(s32 textID) { gCloseTextMessage = TRUE; } -s32 func_800C3400(void) { +/** + * Returns nonzero if a textbox is visible. + * The number depends on what kind it is. + */ +s32 textbox_visible(void) { s32 result = 0; if (gTextTableExists) { if (gShowOnscreenMessage) { result = 1; - if (D_8012A788 != 0) { + if (D_8012A788) { result = 2; } } diff --git a/src/game_text.h b/src/game_text.h index 745fdca1..41c7825f 100644 --- a/src/game_text.h +++ b/src/game_text.h @@ -60,7 +60,7 @@ void free_game_text_table(void); void set_textbox_display_value(s32 num); void reset_delayed_text(void); void set_delayed_text(s32 textID, f32 delay); -s32 func_800C3400(void); +s32 textbox_visible(void); void process_onscreen_textbox(s32 updateRate); void find_next_subtitle(void); s32 func_800C38B4(s32 arg0, TextBox *textbox); diff --git a/src/game_ui.c b/src/game_ui.c index c725007a..f7bfc9ef 100644 --- a/src/game_ui.c +++ b/src/game_ui.c @@ -305,7 +305,7 @@ void init_hud(UNUSED s32 viewportCount) { gHudAudioData[i].volumeRamp = 0; gHudAudioData[i].playerIndex = PLAYER_COMPUTER; if (gHudAudioData[i].soundMask) { - func_8000488C(gHudAudioData[i].soundMask); + sound_stop(gHudAudioData[i].soundMask); } } } @@ -360,7 +360,7 @@ void render_hud(Gfx **dList, MatrixS **mtx, Vertex **vertexList, Object *obj, s3 } gHudLevelHeader = get_current_level_header(); if (obj == NULL) { - if (get_cutscene_id() == 10) { + if (cutscene_id() == 10) { obj = get_racer_object_by_port(PLAYER_ONE); } } @@ -389,7 +389,7 @@ void render_hud(Gfx **dList, MatrixS **mtx, Vertex **vertexList, Object *obj, s3 D_80126D10 = racer->playerIndex; } gCurrentHud = gPlayerHud[gHudCurrentViewport]; - if (get_cutscene_id() != 10) { + if (cutscene_id() != 10) { if (gHUDNumPlayers == ONE_PLAYER) { if (get_buttons_pressed_from_player(D_80126D10) & D_CBUTTONS && racer->raceFinished == FALSE && ((gHudLevelHeader->race_type == RACETYPE_DEFAULT) || @@ -482,7 +482,7 @@ void render_hud(Gfx **dList, MatrixS **mtx, Vertex **vertexList, Object *obj, s3 if (is_in_time_trial()) { func_800A277C(countdown, obj, updateRate); } else { - if (get_cutscene_id() == 10) { + if (cutscene_id() == 10) { sprite_anim_off(TRUE); render_balloon_count(racer); sprite_anim_off(FALSE); @@ -555,7 +555,7 @@ void hud_audio_init(void) { s32 i; for (i = 0; i < 2; i++) { if (gHudAudioData[i].soundMask) { - func_8000488C(gHudAudioData[i].soundMask); + sound_stop(gHudAudioData[i].soundMask); gHudAudioData[i].soundMask = NULL; gHudAudioData[i].volume = 0; } @@ -605,7 +605,7 @@ void hud_audio_update(s32 updateRate) { } } else { if (gHudAudioData[i].soundMask) { - func_8000488C(gHudAudioData[i].soundMask); + sound_stop(gHudAudioData[i].soundMask); gHudAudioData[i].soundMask = 0; } } @@ -1322,8 +1322,8 @@ void func_800A277C(s32 arg0, Object *playerRacerObj, s32 updateRate) { } } } - if (func_8001B288()) { - ttSWBodyObject = func_8001B2E0(); + if (timetrial_valid_player_ghost()) { + ttSWBodyObject = timetrial_player_ghost(); if (ttSWBodyObject != NULL) { if ((get_race_countdown() == 0) && (curRacer->raceFinished == 0)) { posY = ttSWBodyObject->segment.trans.y_position - playerRacerObj->segment.trans.y_position; @@ -1443,9 +1443,9 @@ void set_stopwatch_face(u8 arg0, u8 arg1, u8 faceID, u8 arg3, u8 arg4) { } } -/** +/** * Reset the angle of the speedometre's needle to the starting position. -*/ + */ void hud_speedometre_reset(void) { gCurrentHud->speedometreArrow.z_rotation = 0x6490; } @@ -1596,7 +1596,7 @@ void render_race_start(s32 countdown, s32 updateRate) { } if (gRaceStartShowHudStep == 3) { sound_play(SOUND_VOICE_TT_GO, &gHUDVoiceSoundMask); - if (get_time_trial_ghost() && unbeaten_staff_time() == FALSE) { + if (timetrial_ghost_staff() && timetrial_staff_unbeaten() == FALSE) { hud_sound_play_delayed(SOUND_VOICE_TT_BEAT_MY_TIME, 1.7f, PLAYER_ONE); set_delayed_text(ASSET_GAME_TEXT_82, 1.7f); // Now try and beat my time! } @@ -2388,7 +2388,7 @@ void func_800A6254(Object_Racer *racer, s32 updateRate) { sound_play(SOUND_VOICE_TT_UNLUCKY, &gHUDVoiceSoundMask); break; } - } else if (get_time_trial_ghost() == NULL) { + } else if (timetrial_ghost_staff() == NULL) { play_time_trial_end_message(&racer->playerIndex); } } @@ -2552,11 +2552,11 @@ void render_balloon_count(UNUSED Object_Racer *racer) { if (settings->cutsceneFlags & CUTSCENE_ADVENTURE_TWO) { gCurrentHud->balloonCountIcon.spriteID = HUD_SPRITE_BALLOON_DIAMOND; // Use the adventure two balloon sprite. } - if (get_cutscene_id() == 10 && get_balloon_cutscene_timer() < balloonTickTimer) { + if (cutscene_id() == 10 && get_balloon_cutscene_timer() < balloonTickTimer) { balloonCount = *settings->balloonsPtr - 1; } else { balloonCount = *settings->balloonsPtr; - if (get_cutscene_id() == 10) { + if (cutscene_id() == 10) { if (get_balloon_cutscene_timer() < balloonTickTimer + 8 && D_80126D44 == NULL) { sound_play(SOUND_HUD_LAP_TICK, &D_80126D44); } @@ -3244,8 +3244,8 @@ void render_minimap_and_misc_hud(Gfx **dList, MatrixS **mtx, Vertex **vtx, s32 u sp11C = (lvlMdl->upperXBounds - lvlMdl->lowerXBounds) / (f32) (lvlMdl->upperZBounds - lvlMdl->lowerZBounds); sp118 = coss_f((lvlMdl->minimapRotation * 0xFFFF) / 360); sp114 = sins_f((lvlMdl->minimapRotation * 0xFFFF) / 360); - if (is_in_time_trial() && func_8001B288()) { - temp_v0_8 = func_8001B2E0(); + if (is_in_time_trial() && timetrial_valid_player_ghost()) { + temp_v0_8 = timetrial_player_ghost(); if (temp_v0_8 != NULL) { minimap_marker_pos(temp_v0_8->segment.trans.x_position, temp_v0_8->segment.trans.z_position, sp114, sp118, sp11C); @@ -3257,7 +3257,7 @@ void render_minimap_and_misc_hud(Gfx **dList, MatrixS **mtx, Vertex **vtx, s32 u func_800AA600(&gHUDCurrDisplayList, &gHUDCurrMatrix, &gHUDCurrVertex, &gCurrentHud->minimapMarker); } } - temp_v0_8 = get_time_trial_ghost(); + temp_v0_8 = timetrial_ghost_staff(); if (temp_v0_8 != NULL) { minimap_marker_pos(temp_v0_8->segment.trans.x_position, temp_v0_8->segment.trans.z_position, sp114, sp118, sp11C); @@ -3317,15 +3317,15 @@ void render_minimap_and_misc_hud(Gfx **dList, MatrixS **mtx, Vertex **vtx, s32 u gCurrentHud->minimapMarker.x -= 4.0f; } if (get_current_level_race_type() == RACETYPE_CHALLENGE_BATTLE) { - switch (someRacer->unk212) { - case 0: + switch (someRacer->elevation) { + case ELEVATION_LOW: gCurrentHud->minimapMarker.scale = 0.8f; break; - case 1: + case ELEVATION_NORMAL: gCurrentHud->minimapMarker.scale = 1.0f; break; - case 2: - case 3: + case ELEVATION_HIGH: + case ELEVATION_HIGHEST: gCurrentHud->minimapMarker.scale = 1.2f; break; } @@ -3368,22 +3368,18 @@ void minimap_marker_pos(f32 x, f32 z, f32 angleSin, f32 angleCos, f32 modelAspec scaledY = (lvlMdl->minimapYScale * -60.0f * (z - lvlMdl->lowerZBounds)) / b; if (get_filtered_cheats() & CHEAT_MIRRORED_TRACKS) { // Is adventure 2? - gCurrentHud->minimapMarker.x = (((f32) gMinimapScreenX - ((scaledX * angleCos) + (scaledY * angleSin))) + - (f32) lvlMdl->minimapOffsetXAdv2) - - (f32) gMinimapDotOffsetX; - gCurrentHud->minimapMarker.y = - ((f32) (lvlMdl->minimapOffsetYAdv2 + gMinimapScreenY) - ((scaledX * angleSin) - (scaledY * angleCos))) + - (f32) gMinimapDotOffsetY; + gCurrentHud->minimapMarker.x = (gMinimapScreenX - ((scaledX * angleCos) + (scaledY * angleSin))) + + lvlMdl->minimapOffsetXAdv2 - gMinimapDotOffsetX; + gCurrentHud->minimapMarker.y = (lvlMdl->minimapOffsetYAdv2 + gMinimapScreenY) - + ((scaledX * angleSin) - (scaledY * angleCos)) + gMinimapDotOffsetY; return; } // Final x position on minimap - gCurrentHud->minimapMarker.x = - ((f32) gMinimapScreenX + ((scaledX * angleCos) + (scaledY * angleSin)) + (f32) lvlMdl->minimapOffsetXAdv1) - - (f32) gMinimapDotOffsetX; + gCurrentHud->minimapMarker.x = gMinimapScreenX + ((scaledX * angleCos) + (scaledY * angleSin)) + + (f32) lvlMdl->minimapOffsetXAdv1 - gMinimapDotOffsetX; // Final y position on minimap - gCurrentHud->minimapMarker.y = - ((f32) (lvlMdl->minimapOffsetYAdv1 + gMinimapScreenY) - ((scaledX * angleSin) - (scaledY * angleCos))) + - (f32) gMinimapDotOffsetY; + gCurrentHud->minimapMarker.y = (lvlMdl->minimapOffsetYAdv1 + gMinimapScreenY) - + ((scaledX * angleSin) - (scaledY * angleCos)) + gMinimapDotOffsetY; } // hud_draw_element diff --git a/src/menu.c b/src/menu.c index 33b2c4af..8cde1d58 100644 --- a/src/menu.c +++ b/src/menu.c @@ -56,9 +56,7 @@ unk801263C0 gMenuCurrentCharacter; s32 gIgnorePlayerInputTime; // A set amount of time to ignore player input. UNUSED s32 sUnused_801263C8; // Set to 0 in menu_init, and never again. -CharacterSelectData ( - *gCurrCharacterSelectData)[10]; // Some sort of character list? Cares if T.T. and Drumstick are unlocked - +CharacterSelectData (*gCurrCharacterSelectData)[10]; s32 D_801263D0; // Compared for equality to gTrackIdForPreview s8 gActivePlayersArray[MAXCONTROLLERS]; // Boolean value for each controller if it's active with a player. s32 gOpacityDecayTimer; @@ -4306,7 +4304,7 @@ s32 menu_audio_options_loop(s32 updateRate) { sound_play(SOUND_VOICE_DIDDY_POSITIVE5, (s32 *) &D_801269FC); } } else if (D_801269FC != NULL) { - func_8000488C((u8 *) D_801269FC); + sound_stop((u8 *) D_801269FC); } if (sp30 == 3) { sound_play(SOUND_MENU_BACK3, NULL); @@ -4328,7 +4326,7 @@ s32 menu_audio_options_loop(s32 updateRate) { void func_800851FC(void) { if (D_801269FC != NULL) { - func_8000488C(D_801269FC); + sound_stop(D_801269FC); } if (gOpacityDecayTimer >= 0) { music_voicelimit_set(24); @@ -6813,7 +6811,7 @@ void func_8008B4C8(void) { } } if (D_80126808[characterSelected] != 0) { - func_8000488C(D_80126808[characterSelected]); + sound_stop(D_80126808[characterSelected]); } sound_play(((*gCurrCharacterSelectData)[gPlayersCharacterArray[characterSelected]].voiceID + SOUND_VOICE_CHARACTER_SELECTED), @@ -6831,7 +6829,7 @@ void func_8008B4C8(void) { D_801263DC[i] = 0; gNumberOfReadyPlayers--; if (D_80126808[i] != 0) { - func_8000488C(D_80126808[i]); + sound_stop(D_80126808[i]); } sound_play(((*gCurrCharacterSelectData)[gPlayersCharacterArray[i]].voiceID + SOUND_VOICE_CHARACTER_DESELECTED), @@ -6855,7 +6853,7 @@ void func_8008B758(s8 *activePlayers) { D_801263DC[i] = 0; gNumberOfReadyPlayers -= 1; if (D_80126808[i] != 0) { - func_8000488C(D_80126808[i]); + sound_stop(D_80126808[i]); } sound_play(((*gCurrCharacterSelectData)[gPlayersCharacterArray[i]].voiceID + SOUND_VOICE_CHARACTER_DESELECTED), @@ -6890,7 +6888,7 @@ void func_8008B758(s8 *activePlayers) { D_801263DC[i] = 1; gNumberOfReadyPlayers++; if (D_80126808[i] != 0) { - func_8000488C(D_80126808[i]); + sound_stop(D_80126808[i]); } sound_play( ((*gCurrCharacterSelectData)[gPlayersCharacterArray[i]].voiceID + SOUND_VOICE_CHARACTER_SELECT), @@ -10298,9 +10296,9 @@ s32 func_80095728(Gfx **dlist, MatrixS **matrices, Vertex **vertices, s32 update D_80126A98++; if (D_80126A98 >= 5) { sound_volume_change(3); - sp54 = func_8001B738(0); + sp54 = timetrial_save_player_ghost(0); if ((sp54 & 0xFF) == 5) { - sp54 = func_8001B738(0); + sp54 = timetrial_save_player_ghost(0); } sound_volume_change(2); if (sp54 != 0) { @@ -12427,7 +12425,7 @@ s8 *func_8009C274(void) { * Returns the character Id from a controller index. */ s8 get_player_character(s32 controllerIndex) { - if (controllerIndex < 0 || controllerIndex >= 4) { + if (controllerIndex < 0 || controllerIndex >= MAXCONTROLLERS) { return -1; } if (!gActivePlayersArray[controllerIndex]) { @@ -12789,7 +12787,7 @@ s32 npc_dialogue_loop(u32 dialogueOption) { s32 result; gDoneTalkingToNPC[dialogueOption] = 0; - if ((func_800C3400() != 0) && (dialogueOption != DIALOGUE_CHALLENGE)) { + if ((textbox_visible() != 0) && (dialogueOption != DIALOGUE_CHALLENGE)) { return 0; } if (gNeedToCloseDialogueBox) { @@ -13294,9 +13292,9 @@ s32 tt_menu_loop(void) { HORZ_ALIGN_CENTER); // PLEASE WAIT gSaveGhostDelayCounter++; if (gSaveGhostDelayCounter >= 5) { - result = func_8001B738(0); + result = timetrial_save_player_ghost(0); if (result == CONTROLLER_PAK_CHANGED) { - result = func_8001B738(0); + result = timetrial_save_player_ghost(0); } switch (result) { case CONTROLLER_PAK_GOOD: diff --git a/src/object_functions.c b/src/object_functions.c index 8ed29608..dd42361e 100644 --- a/src/object_functions.c +++ b/src/object_functions.c @@ -31,6 +31,7 @@ #include "lib/src/libc/rmonPrintf.h" #include "collision.h" #include "controller.h" +#include "printf.h" /************ .data ************/ @@ -142,7 +143,7 @@ void obj_init_scenery(Object *obj, LevelObjectEntry_Scenery *entry) { */ void obj_loop_scenery(Object *obj, s32 updateRate) { ObjPropertyScenery *properties; - s32 temp_v0; + s32 particleFlagShift; if (obj->interactObj != NULL) { properties = &obj->properties.scenery; @@ -156,14 +157,14 @@ void obj_loop_scenery(Object *obj, s32 updateRate) { properties->angleVel = 0x71C; properties->hitTimer = 10; if (get_number_of_active_players() < 2) { - if (obj->segment.header->unk57 > 0) { - if (obj->segment.header->unk57 == 1) { - temp_v0 = 0; + if (obj->segment.header->particleCount > 0) { + if (obj->segment.header->particleCount == 1) { + particleFlagShift = 0; } else { - temp_v0 = get_random_number_from_range(0, obj->segment.header->unk57 - 1); + particleFlagShift = get_random_number_from_range(0, obj->segment.header->particleCount - 1); } - obj->unk74 = 1 << temp_v0; - func_800AFC3C(obj, 2); + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_1 << particleFlagShift; + obj_spawn_particle(obj, LOGIC_30FPS); } } } else if (properties->hitTimer <= 0) { @@ -277,8 +278,8 @@ void obj_loop_fireball_octoweapon(Object *obj, s32 updateRate) { } } if (obj->behaviorId == BHV_FIREBALL_OCTOWEAPON) { - obj->unk74 = 1; - func_800AFC3C(obj, updateRate); + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; + obj_spawn_particle(obj, updateRate); obj->properties.fireball.timer -= updateRate; if (obj->properties.fireball.timer < 0) { if (obj->objectID == ASSET_OBJECT_ID_OCTOBOMB) { @@ -307,7 +308,7 @@ void obj_loop_fireball_octoweapon(Object *obj, s32 updateRate) { if (obj->properties.fireball.timer == 0) { soundMask = weapon->soundMask; if (soundMask != NULL) { - func_8000488C(soundMask); + sound_stop(soundMask); } play_sound_at_position(SOUND_POP, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); @@ -637,7 +638,7 @@ void obj_loop_trophycab(Object *obj, s32 updateRate) { if (worldBalloons) { worldBalloons = ((1 << (settings->worldId + 6)) & bossFlags) != 0; } - if (obj->properties.trophyCabinet.action == NULL && func_800C3400() == FALSE) { + if (obj->properties.trophyCabinet.action == NULL && textbox_visible() == FALSE) { if (obj->unk5C->unk100 != NULL) { if (gfxData->unk4 == 0) { if (worldBalloons) { @@ -666,7 +667,7 @@ void obj_loop_trophycab(Object *obj, s32 updateRate) { music_jingle_voicelimit_set(6); } } - if (obj->unk5C->unk100 != NULL || func_800C3400()) { + if (obj->unk5C->unk100 != NULL || textbox_visible()) { gfxData->unk4 = 180; } if (gfxData->unk4 > 0) { @@ -1039,13 +1040,22 @@ void obj_loop_groundzipper(Object *obj, UNUSED s32 updateRate) { } } -// This I'm quite sure is related to time trial checkpoints. -void obj_init_unknown58(Object *obj, UNUSED LevelObjectEntry_Unknown58 *entry) { - obj->properties.common.unk0 = 0; - obj->properties.common.unk4 = (s32) obj->segment.header; +/** + * Time Trial Ghost init func. + * Sets the timestamp frame to 0 + */ +void obj_init_timetrialghost(Object *obj, UNUSED LevelObjectEntry_TimeTrial_Ghost *entry) { + obj->properties.timeTrial.timestamp = 0; + obj->properties.timeTrial.header = obj->segment.header; } -void obj_loop_unknown58(Object *obj, s32 updateRate) { +/** + * Time Trial Ghost loop func. + * Reads the ghost data associated with the header, + * then has the position and rotation manually set to simulate time trial playback. + * Has particle data, but never used. + */ +void obj_loop_timetrialghost(Object *obj, s32 updateRate) { Object *someObj; Object *someOtherObj; Object_UnkId58 *someOtherObj64; @@ -1055,10 +1065,10 @@ void obj_loop_unknown58(Object *obj, s32 updateRate) { obj->segment.object.animationID = 0; obj->segment.animFrame = 40; if (get_race_countdown() == 0) { - obj->properties.common.unk0 += updateRate; + obj->properties.timeTrial.timestamp += updateRate; } set_ghost_position_and_rotation(obj); - func_800AFC3C(obj, updateRate); + obj_spawn_particle(obj, updateRate); someOtherObj = get_racer_object(PLAYER_ONE); someOtherObj64 = &someOtherObj->unk64->unkid58; obj60 = obj->unk60; @@ -1073,10 +1083,15 @@ void obj_loop_unknown58(Object *obj, s32 updateRate) { } } +/** + * Character World Portrait init func. + * Sets the scale, but the actual geometry data is built during the update loop. + * These are seen in the challenge maps. + */ void obj_init_characterflag(Object *obj, LevelObjectEntry_CharacterFlag *entry) { f32 radius; obj->properties.characterFlag.playerID = entry->playerIndex; - obj->properties.characterFlag.characterID = -1; + obj->properties.characterFlag.characterID = -1; // Set to -1 so the loop func builds the gfx data. obj->segment.trans.y_rotation = U8_ANGLE_TO_U16(entry->angleY); radius = entry->radius & 0xFF; if (radius < 10.0f) { @@ -1086,6 +1101,11 @@ void obj_init_characterflag(Object *obj, LevelObjectEntry_CharacterFlag *entry) obj->segment.trans.scale = obj->segment.header->scale * radius; } +/** + * Character World Portrait loop func. + * If there's no associated character ID, build the portrait geometry + * and set the texture based on the character ID, then write the character ID. + */ void obj_loop_characterflag(Object *obj, UNUSED s32 updateRate) { s32 temp_t4; s32 temp_t5; @@ -1264,7 +1284,7 @@ void obj_loop_stopwatchman(Object *obj, s32 updateRate) { switch (obj->properties.npc.action) { case TT_MODE_APPROACH_PLAYER: obj->segment.object.animationID = 0; - tt->unkD = 255; + tt->nodeCurrent = 255; if (distance < 100.0) { racer_set_dialogue_camera(); } @@ -1350,14 +1370,14 @@ void obj_loop_stopwatchman(Object *obj, s32 updateRate) { default: obj->segment.object.animationID = 0; tt->forwardVel = 0.0f; - if (tt->unkD == 0xFF) { - tt->unkD = func_8001C524(obj->segment.trans.x_position, obj->segment.trans.y_position, - obj->segment.trans.z_position, 0); - if (tt->unkD != 0xFF) { - tt->unkE = func_8001CC48(tt->unkD, -1, 0); - tt->unkF = func_8001CC48(tt->unkE, tt->unkD, 0); - tt->unk10 = func_8001CC48(tt->unkF, tt->unkE, 0); - tt->unkC = tt->unkD; + if (tt->nodeCurrent == NODE_NONE) { + tt->nodeCurrent = ainode_find_nearest(obj->segment.trans.x_position, obj->segment.trans.y_position, + obj->segment.trans.z_position, FALSE); + if (tt->nodeCurrent != NODE_NONE) { + tt->nodeBack2 = func_8001CC48(tt->nodeCurrent, -1, 0); + tt->nodeForward1 = func_8001CC48(tt->nodeBack2, tt->nodeCurrent, 0); + tt->nodeForward2 = func_8001CC48(tt->nodeForward1, tt->nodeBack2, 0); + tt->nodeBack1 = tt->nodeCurrent; } } else { diffZ = func_8001C6C4((Object_64 *) tt, obj, updateRateF, 1.0f, 0); @@ -1399,7 +1419,7 @@ void obj_loop_stopwatchman(Object *obj, s32 updateRate) { */ void play_tt_voice_clip(u16 soundID, s32 interrupt) { if (gTTSoundMask && interrupt & 1) { - func_8000488C(gTTSoundMask); // This is likely wrong and will need to be fixed + sound_stop(gTTSoundMask); // This is likely wrong and will need to be fixed gTTSoundMask = NULL; } if (gTTSoundMask == NULL) { @@ -1784,7 +1804,7 @@ void obj_init_animation(Object *obj, LevelObjectEntry_Animation *entry, s32 arg2 func_8001F3C8(entry->actorIndex); } if (entry->channel == -1) { - entry->channel = get_cutscene_id(); + entry->channel = cutscene_id(); } if (entry->channel == 20) { entry->actorIndex |= 0x80; @@ -1803,19 +1823,19 @@ void obj_init_animation(Object *obj, LevelObjectEntry_Animation *entry, s32 arg2 entry->order = 0; } } - func_80011390(); + path_enable(); obj->properties.animatedObj.behaviourID = entry->actorIndex; obj->properties.animatedObj.action = arg2; if (arg2 != 0 && (get_buttons_pressed_from_player(PLAYER_ONE) & R_CBUTTONS)) { obj->properties.animatedObj.action = 2; } - if (((get_cutscene_id() == entry->channel) || (entry->channel == 20)) && (obj->unk64 == NULL) && - (entry->order == 0) && (entry->objectIdToSpawn != -1)) { + if (((cutscene_id() == entry->channel) || (entry->channel == 20)) && (obj->unk64 == NULL) && (entry->order == 0) && + (entry->objectIdToSpawn != -1)) { func_8001F23C(obj, entry); } obj64 = &obj->unk64->animation; if (obj->unk64 != 0) { - func_8001EFA4(obj, (Object *) obj64); + obj_init_animcamera(obj, (Object *) obj64); if (entry->order != 0 || obj64->unk4A != entry->objectIdToSpawn) { free_object((Object *) obj64); obj->unk64 = NULL; @@ -1831,15 +1851,15 @@ void obj_loop_animobject(Object *obj, s32 updateRate) { } void obj_loop_dooropener(Object *obj, s32 updateRate) { - s32 phi_a0; - unk80037D08_arg0_64 *sp18; + s32 openDoors; + unk80037D08_arg0_64 *doorOpener; - sp18 = (unk80037D08_arg0_64 *) obj->unk64; - phi_a0 = 1 - func_8001F460(obj, updateRate, obj); - if (sp18->unk2A > 0) { - phi_a0 = 0; + doorOpener = (unk80037D08_arg0_64 *) obj->unk64; + openDoors = 1 - func_8001F460(obj, updateRate, obj); + if (doorOpener->unk2A > 0) { + openDoors = FALSE; } - func_800235D0(phi_a0); + obj_door_open(openDoors); } void obj_init_overridepos(UNUSED Object *obj, UNUSED LevelObjectEntry_OverridePos *entry) { @@ -1881,7 +1901,7 @@ void obj_loop_wizpigship(Object *wizShipObj, s32 updateRate) { wizShipObj->properties.fireball.timer = 0; } if ((wizShipObj->unk60 != NULL) && (wizShipObj->properties.fireball.timer == 0)) { - if (wizShipObj->unk74 & 1) { + if (wizShipObj->particleEmitFlags & OBJ_EMIT_PARTICLE_1) { wizShipObj->properties.fireball.timer = 20; object_transform_to_matrix(shipMtx, &wizShipObj->segment.trans); trans.x_position = 0.0f; @@ -1986,14 +2006,14 @@ void obj_init_snowball(Object *obj, UNUSED LevelObjectEntry_Snowball *entry) { void obj_loop_snowball(Object *obj, s32 updateRate) { Object_AnimatedObject *obj64 = &obj->unk64->animatedObject; - if (obj64->unk24 == 0) { - if (obj64->unk38 != 0) { - obj64->unk24 = (s16) (obj64->unk38 & 0xFF); + if (obj64->currentSound == SOUND_NONE) { + if (obj64->soundID != SOUND_NONE) { + obj64->currentSound = obj64->soundID & 0xFF; } } - if (obj64->unk24 != 0) { + if (obj64->currentSound != SOUND_NONE) { if (obj64->soundMask == NULL) { - play_sound_at_position(obj64->unk24, obj->segment.trans.x_position, obj->segment.trans.y_position, + play_sound_at_position(obj64->currentSound, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 1, (SoundMask **) &obj64->soundMask); } else { update_spatial_audio_position((SoundMask *) obj64->soundMask, obj->segment.trans.x_position, @@ -2016,10 +2036,10 @@ void obj_loop_char_select(Object *charSelectObj, s32 updateRate) { f32 temp_f0; ObjectModel *objMdl; Object_CharacterSelect *charSelect; - s32 var_a0; + s32 charCount; s32 var_s0; - s8 *var_v0; - Object_68 *obj68; + s8 *var_v0 = NULL; + Object_68 *gfxData; u8 sp50[4]; u8 sp4F; u8 *var_a2; @@ -2027,28 +2047,28 @@ void obj_loop_char_select(Object *charSelectObj, s32 updateRate) { var_s0 = 0; func_8001F460(charSelectObj, updateRate, NULL); charSelect = &charSelectObj->unk64->characterSelect; - charSelectObj->unk74 = 0; + charSelectObj->particleEmitFlags = OBJ_EMIT_OFF; if (charSelect != NULL) { - obj68 = charSelectObj->unk68[charSelectObj->segment.object.modelIndex]; - if (obj68 != NULL) { - objMdl = obj68->objModel; + gfxData = charSelectObj->unk68[charSelectObj->segment.object.modelIndex]; + if (gfxData != NULL) { + objMdl = gfxData->objModel; if (is_drumstick_unlocked()) { if (is_tt_unlocked()) { var_a2 = D_800DCA70; - var_a0 = 10; + charCount = 10; } else { var_a2 = D_800DCA58; - var_a0 = 9; + charCount = 9; } } else if (is_tt_unlocked()) { var_a2 = D_800DCA64; - var_a0 = 9; + charCount = 9; } else { var_a2 = D_800DCA50; - var_a0 = 8; + charCount = 8; } - for (i = 0; i < var_a0 && !var_s0; i++) { + for (i = 0; i < charCount && !var_s0; i++) { if (charSelect->unk28 == var_a2[i]) { var_s0 = 1; } @@ -2073,8 +2093,8 @@ void obj_loop_char_select(Object *charSelectObj, s32 updateRate) { var_v0 = func_8009C274(); for (i2 = 0; i2 < sp4F; i2++) { if (var_v0[sp50[i2]] == 1) { - charSelectObj->unk74 = 1; - func_800AFC3C(charSelectObj, 2); + charSelectObj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; + obj_spawn_particle(charSelectObj, LOGIC_30FPS); } } @@ -2108,22 +2128,26 @@ void obj_loop_char_select(Object *charSelectObj, s32 updateRate) { } } +/** + * Camera Animation loop func. + * Follows a path and then writes to the view perspective. + */ void obj_loop_animcamera(Object *obj, s32 updateRate) { s32 temp_v0; - s32 phi_v1; - Object_AnimCamera *obj64; + s32 updateCam; + Object_Animation *camera; temp_v0 = func_8001F460(obj, updateRate, obj); obj->segment.trans.flags |= OBJ_FLAGS_INVISIBLE; - obj64 = &obj->unk64->anim_camera; + camera = &obj->unk64->animation; if (temp_v0 == 0) { if (get_viewport_count() == VIEWPORTS_COUNT_1_PLAYER) { - phi_v1 = func_800210CC(obj64->unk44); + updateCam = func_800210CC(camera->unk44); } else { - phi_v1 = 1; + updateCam = TRUE; } - if (phi_v1) { - write_to_object_render_stack(obj64->unk30, obj->segment.trans.x_position, obj->segment.trans.y_position, + if (updateCam) { + write_to_object_render_stack(camera->cameraID, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 0x8000 - obj->segment.trans.y_rotation, -obj->segment.trans.x_rotation, obj->segment.trans.z_rotation); } @@ -2158,7 +2182,7 @@ void obj_loop_animcar(Object *obj, s32 updateRate) { } void obj_init_infopoint(Object *obj, LevelObjectEntry_InfoPoint *entry) { - if (entry->unk8[1] != 0) { + if (entry->hitbox[1] != 0) { obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0020; } else { obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE | INTERACT_FLAGS_UNK_0020; @@ -2166,8 +2190,8 @@ void obj_init_infopoint(Object *obj, LevelObjectEntry_InfoPoint *entry) { obj->interactObj->unk11 = 0; obj->interactObj->hitboxRadius = 15; obj->interactObj->pushForce = 0; - obj->properties.infoPoint.radius = (entry->unk8[2] << 16) | entry->unk8[0]; // Not sure about the values here. - obj->properties.infoPoint.visible = entry->unk8[1]; + obj->properties.infoPoint.radius = (entry->hitbox[2] << 16) | entry->hitbox[0]; // Not sure about the values here. + obj->properties.infoPoint.visible = entry->hitbox[1]; obj->segment.trans.y_rotation = entry->unkB << 10; // Not sure about the values here. } @@ -2253,7 +2277,7 @@ void obj_init_bombexplosion(Object *obj, LevelObjectEntry_BombExplosion *entry) if (entry->unk8) { obj->properties.bombExplosion.unk4 |= (entry2->unk8 << 8) & 0xFF00; } - obj->unk74 = 1; + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; } void obj_loop_bombexplosion(Object *obj, s32 updateRate) { @@ -2276,10 +2300,10 @@ void obj_loop_bombexplosion(Object *obj, s32 updateRate) { free_object(obj); } - if (obj->unk74 != 0) { + if (obj->particleEmitFlags) { if (get_number_of_active_players() < THREE_PLAYERS) { - func_800AFC3C(obj, 2); - obj->unk74 = 0; + obj_spawn_particle(obj, LOGIC_30FPS); + obj->particleEmitFlags = OBJ_EMIT_OFF; } } } @@ -2400,20 +2424,36 @@ void obj_loop_exit(Object *obj, UNUSED s32 updateRate) { } } +/** + * Spectate Camera init func. + * Sets the camera ID then signals to update the pathing systems which include spectate cameras. + */ void obj_init_cameracontrol(Object *obj, LevelObjectEntry_CameraControl *entry) { - obj->properties.common.unk0 = entry->unk8; - func_80011390(); + obj->properties.camControl.cameraID = entry->cameraID; + path_enable(); } +/** + * Spectate Cameras loop func. + * Does nothing since all the behaviour is handled globally. + */ void obj_loop_cameracontrol(UNUSED Object *obj, UNUSED s32 updateRate) { } +/** + * Racer Spawnpoint init func. + * Sets the spawn ID as well as racer index. + */ void obj_init_setuppoint(Object *obj, LevelObjectEntry_SetupPoint *entry) { - obj->properties.common.unk0 = entry->unk8; - obj->properties.common.unk4 = entry->unk9; + obj->properties.setupPoint.racerIndex = entry->racerIndex; + obj->properties.setupPoint.entranceID = entry->entranceID; obj->segment.trans.y_rotation = U8_ANGLE_TO_U16(entry->angleY); } +/** + * Racer Spawnpoint loop func. + * Does nothing by itself; the game will use these as an anchor for spawning racer objects. + */ void obj_loop_setuppoint(UNUSED Object *obj, UNUSED s32 updateRate) { } @@ -2464,7 +2504,7 @@ void obj_init_parkwarden(Object *obj, UNUSED LevelObjectEntry_Parkwarden *entry) obj->interactObj->hitboxRadius = 30; obj->interactObj->pushForce = 0; taj = &obj->unk64->npc; - taj->unkD = 0xFF; + taj->nodeCurrent = 0xFF; taj->unk0 = 0.0f; taj->unk28 = 0; taj->unk2C = 0; @@ -2506,14 +2546,14 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { Object_NPC *taj; Object_Racer *racer; u32 buttonsPressed; - s8 sp6B; + s8 spawnSmoke; LevelHeader *levelHeader; ObjectSegment *temp_v0_22; f32 var_f2; s32 arctan; s32 temp; - sp6B = 0; + spawnSmoke = FALSE; tempPosY = obj->segment.trans.y_position; updateRateF2 = updateRate; @@ -2523,7 +2563,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { } taj = (Object_NPC *) obj->unk64; levelHeader = get_current_level_header(); - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; if (obj->segment.animFrame == 0 && taj->animFrameF > 1.0) { taj->animFrameF = 0.0f; } @@ -2569,7 +2609,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { racer_sound_free(racerObj); racer->vehicleSound = NULL; } - func_80008140(); + audioline_off(); arctan = arctan2_f(racerObj->segment.trans.x_position - obj->segment.trans.x_position, racerObj->segment.trans.z_position - obj->segment.trans.z_position); arctan -= (racerObj->segment.trans.y_rotation & 0xFFFF); @@ -2582,7 +2622,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { obj->properties.npc.action = TAJ_MODE_APPROACH_PLAYER; } else { obj->properties.npc.action = TAJ_MODE_TELEPORT_TO_PLAYER_BEGIN; - sp6B = 1; + spawnSmoke = TRUE; } get_fog_settings(PLAYER_ONE, &taj->fogNear, &taj->fogFar, &taj->fogR, &taj->fogG, &taj->fogB); slowly_change_fog(PLAYER_ONE, 255, 0, 120, 960, 1100, 240); @@ -2629,7 +2669,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { switch (obj->properties.npc.action) { case TAJ_MODE_APPROACH_PLAYER: obj->segment.object.animationID = 0; - taj->unkD = 0xFF; + taj->nodeCurrent = 0xFF; if (distance < 100.0) { racer_set_dialogue_camera(); } @@ -2715,7 +2755,8 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { taj->animFrameF += updateRateF * 1.0; racer_set_dialogue_camera(); if (dialogueID == 3 || dialogueID == 4) { - obj->properties.npc.action = (dialogueID == 4) ? TAJ_MODE_END_DIALOGUE_UNUSED : TAJ_MODE_END_DIALOGUE; + obj->properties.npc.action = + (dialogueID == 4) ? TAJ_MODE_END_DIALOGUE_CHALLENGE : TAJ_MODE_END_DIALOGUE; taj->animFrameF = 0.1f; obj->segment.object.animationID = 2; taj->unk1C = 0; @@ -2724,7 +2765,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { music_voicelimit_set(levelHeader->voiceLimit); music_play(levelHeader->music); music_dynamic_set(levelHeader->instruments); - func_80008168(); + audioline_on(); } if (dialogueID & 0x80) { gTajDialogueChoice = dialogueID & 0x7F; @@ -2748,7 +2789,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { } else { obj->properties.npc.action = TAJ_MODE_SET_CHALLENGE; transition_begin(&gTajTransition); - sp6B = 1; + spawnSmoke = TRUE; play_taj_voice_clip(SOUND_WHOOSH4, TRUE); taj->animFrameF = 0.0f; } @@ -2759,10 +2800,10 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { racer_set_dialogue_camera(); taj->animFrameF += updateRateF * 2.0; if (taj->animFrameF > 25.0) { - obj->unk74 = 11; + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_1 | OBJ_EMIT_PARTICLE_2 | OBJ_EMIT_PARTICLE_4; } if (taj->animFrameF > 50.0) { - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; } if (taj->animFrameF > 60.0) { taj->animFrameF = 60.0f; @@ -2795,7 +2836,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { if (taj->animFrameF == 0.0) { if (gTajDialogueChoice & 0x80) { transition_begin(&gTajTransition); - sp6B = 1; + spawnSmoke = TRUE; obj->properties.npc.action = TAJ_MODE_SET_CHALLENGE; sound_play(SOUND_WHOOSH4, NULL); taj->animFrameF = 0.0f; @@ -2808,15 +2849,16 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { } break; case TAJ_MODE_END_DIALOGUE: - case TAJ_MODE_END_DIALOGUE_UNUSED: + case TAJ_MODE_END_DIALOGUE_CHALLENGE: if (taj->animFrameF != 0.0) { taj->animFrameF = taj->animFrameF + (0.5 * updateRateF); } if (taj->animFrameF == 0) { - sp6B = 1; - if (obj->properties.npc.action == TAJ_MODE_END_DIALOGUE_UNUSED) { - func_80022CFC(obj->segment.object.segmentID, obj->segment.trans.x_position - (racer->ox1 * 50.0f), - obj->segment.trans.y_position, obj->segment.trans.z_position - (racer->oz1 * 50.0f)); + spawnSmoke = TRUE; + if (obj->properties.npc.action == TAJ_MODE_END_DIALOGUE_CHALLENGE) { + obj_taj_create_balloon( + obj->segment.object.segmentID, obj->segment.trans.x_position - (racer->ox1 * 50.0f), + obj->segment.trans.y_position, obj->segment.trans.z_position - (racer->oz1 * 50.0f)); } obj->properties.npc.action = TAJ_MODE_TELEPORT_AWAY_BEGIN; sound_play(SOUND_WHOOSH4, NULL); @@ -2825,7 +2867,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { break; case TAJ_MODE_TELEPORT_TO_PLAYER_BEGIN: obj->segment.object.animationID = 3; - taj->unkD = 0xFF; + taj->nodeCurrent = 0xFF; taj->forwardVel = 0.0f; taj->animFrameF += updateRateF * 2.0; if (taj->animFrameF > 79.0f) { @@ -2840,7 +2882,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { obj->segment.object.opacity -= var_a2; } else { sound_play(SOUND_WHOOSH4, NULL); - sp6B = 1; + spawnSmoke = TRUE; obj->segment.object.opacity = 0; obj->properties.npc.action = TAJ_MODE_TELEPORT_TO_PLAYER_END; obj->segment.trans.x_position = racerObj->segment.trans.x_position - (racer->ox1 * 150.0f); @@ -2866,7 +2908,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { break; case TAJ_MODE_SET_CHALLENGE: obj->segment.object.animationID = 3; - taj->unkD = 0xFF; + taj->nodeCurrent = 0xFF; taj->forwardVel = 0.0f; taj->animFrameF += updateRateF * 2.0; if (taj->animFrameF > 79.0f) { @@ -2897,7 +2939,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { break; case TAJ_MODE_TELEPORT_AWAY_BEGIN: obj->segment.object.animationID = 3; - taj->unkD = 0xFF; + taj->nodeCurrent = 0xFF; taj->forwardVel = 0.0f; taj->animFrameF += updateRateF * 2.0; if (taj->animFrameF > 79.0f) { @@ -2944,14 +2986,14 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { default: obj->segment.object.animationID = 0; taj->forwardVel = 0.0f; - if (taj->unkD == 0xFF) { - taj->unkD = func_8001C524(obj->segment.trans.x_position, obj->segment.trans.y_position, - obj->segment.trans.z_position, 0); - if (taj->unkD != 0xFF) { - taj->unkE = func_8001CC48(taj->unkD, -1, 0); - taj->unkF = func_8001CC48(taj->unkE, taj->unkD, 0); - taj->unk10 = func_8001CC48(taj->unkF, taj->unkE, 0); - taj->unkC = taj->unkD; + if (taj->nodeCurrent == NODE_NONE) { + taj->nodeCurrent = ainode_find_nearest(obj->segment.trans.x_position, obj->segment.trans.y_position, + obj->segment.trans.z_position, FALSE); + if (taj->nodeCurrent != NODE_NONE) { + taj->nodeBack2 = func_8001CC48(taj->nodeCurrent, -1, 0); + taj->nodeForward1 = func_8001CC48(taj->nodeBack2, taj->nodeCurrent, 0); + taj->nodeForward2 = func_8001CC48(taj->nodeForward1, taj->nodeBack2, 0); + taj->nodeBack1 = taj->nodeCurrent; } } else { if ((distance < 55.0f) && (taj->unk1C == 0) && (racerObj != NULL)) { @@ -3076,13 +3118,13 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { if (obj->properties.npc.action != TAJ_MODE_ROAM) { gNPCPosY = obj->segment.trans.y_position; } - if (sp6B != 0) { + if (spawnSmoke) { obj_spawn_effect(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, ASSET_OBJECT_ID_WARDENSMOKE, SOUND_NONE, 1.0f, 0); } obj->segment.animFrame = taj->animFrameF * 1.0; func_80061C0C(obj); - func_800AFC3C(obj, updateRate); + obj_spawn_particle(obj, updateRate); } /** @@ -3091,8 +3133,8 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { */ void play_taj_voice_clip(u16 soundID, s32 interrupt) { if (gTajSoundMask && interrupt & 1) { - func_8000488C(gTajSoundMask); - gTajSoundMask = 0; + sound_stop(gTajSoundMask); + gTajSoundMask = NULL; } if (!gTajSoundMask) { sound_play(soundID, &gTajSoundMask); @@ -3122,7 +3164,7 @@ void obj_init_checkpoint(Object *obj, LevelObjectEntry_Checkpoint *entry, UNUSED scale /= 64; obj->segment.trans.scale = scale; obj->segment.trans.y_rotation = U8_ANGLE_TO_U16(entry->angleY); - func_80011390(); + path_enable(); } /** @@ -3173,7 +3215,7 @@ void obj_loop_modechange(Object *obj, UNUSED s32 updateRate) { f32 diffX; f32 diffY; f32 diffZ; - s32 radius_3; + s32 node; s32 i; f32 radiusF; f32 dist; @@ -3204,15 +3246,15 @@ void obj_loop_modechange(Object *obj, UNUSED s32 updateRate) { if (racer->raceFinished == FALSE) { rumble_set(racer->playerIndex, RUMBLE_TYPE_8); } - radius_3 = - func_8001C524(racerObj->segment.trans.x_position, racerObj->segment.trans.y_position, - racerObj->segment.trans.z_position, 0); - if (radius_3 != 0xFF) { - racer->unk158 = func_8001D214(radius_3); + node = ainode_find_nearest(racerObj->segment.trans.x_position, + racerObj->segment.trans.y_position, + racerObj->segment.trans.z_position, FALSE); + if (node != NODE_NONE) { + racer->nodeCurrent = ainode_get(node); } else { - racer->unk158 = NULL; + racer->nodeCurrent = NULL; } - racer->unk15C = NULL; + racer->challengeMarker = NULL; racer->unk19A = 0; } racer->unk198 = obj->segment.trans.y_rotation; @@ -3269,7 +3311,7 @@ void obj_loop_bonus(Object *obj, UNUSED s32 updateRate) { racerObj = racerObjects[i]; racer = &racerObj->unk64->racer; diffY = racerObj->segment.trans.y_position - obj->segment.trans.y_position; - if ((diffY < halfDist) && (-halfDist < diffY)) { + if (diffY < halfDist && -halfDist < diffY) { diffX = racerObj->segment.trans.x_position - obj->segment.trans.x_position; diffZ = racerObj->segment.trans.z_position - obj->segment.trans.z_position; if (sqrtf((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ)) < dist) { @@ -3292,6 +3334,10 @@ void obj_loop_bonus(Object *obj, UNUSED s32 updateRate) { } } +/** + * Golden Balloon init func. + * Assigns the balloon ID either from the entry, or from the balloon ID table. + */ void obj_init_goldenballoon(Object *obj, LevelObjectEntry_GoldenBalloon *entry) { Object_NPC *obj64; f32 scalef; @@ -3315,7 +3361,7 @@ void obj_init_goldenballoon(Object *obj, LevelObjectEntry_GoldenBalloon *entry) scalef /= 64; obj->segment.trans.scale = obj->segment.header->scale * scalef; obj64 = &obj->unk64->npc; - obj64->unkD = 255; + obj64->nodeCurrent = 255; obj64->unk0 = 0.0f; obj->properties.npc.action = 0; if (entry->challengeID) { @@ -3327,6 +3373,12 @@ void obj_init_goldenballoon(Object *obj, LevelObjectEntry_GoldenBalloon *entry) } } +/** + * Golden Balloon loop func. + * Made invisible every frame, but made visible during behaviour if applicable. + * Follows a path, like Taj and T.T, until collected. + * Auto deletes if the ID is already claimed by the save flags. + */ void obj_loop_goldenballoon(Object *obj, s32 updateRate) { LevelObjectEntry *levelEntry; ObjectInteraction *interactObj; @@ -3345,18 +3397,20 @@ void obj_loop_goldenballoon(Object *obj, s32 updateRate) { updateRateF *= 1.2; } isPirated = FALSE; +#ifdef ANTI_TAMPER // AntiPiracy check. Seems to set a flag that prevents collecting balloons. if (IO_READ(0x284) != 0x240B17D7) { isPirated = TRUE; } +#endif speedf = updateRateF; settings = get_settings(); levelEntry = obj->segment.level_entry; flag = 0x10000 << levelEntry->goldenBalloon.balloonID; if (settings->courseFlagsPtr[settings->courseId] & flag) { if (obj->properties.npc.timer > 0) { - obj->unk74 = 2; - func_800AFC3C(obj, updateRate); + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_2; + obj_spawn_particle(obj, updateRate); obj->properties.npc.timer -= updateRate; } else { free_object(obj); @@ -3366,7 +3420,7 @@ void obj_loop_goldenballoon(Object *obj, s32 updateRate) { if (obj->properties.npc.action == 0) { obj->segment.trans.flags &= (0xFFFF - OBJ_FLAGS_INVISIBLE); doubleSpeed = updateRate * 2; - if (obj->segment.object.opacity < (255 - doubleSpeed)) { + if (obj->segment.object.opacity < 255 - doubleSpeed) { obj->segment.object.opacity += doubleSpeed; } else { obj->segment.object.opacity = 255; @@ -3379,7 +3433,7 @@ void obj_loop_goldenballoon(Object *obj, s32 updateRate) { if (racer->playerIndex == PLAYER_ONE) { settings->balloonsPtr[settings->worldId]++; if (isPirated == 1) {} // Fakematch - if (settings->worldId != 0) { + if (settings->worldId != WORLD_CENTRAL_AREA) { settings->balloonsPtr[0]++; } settings->courseFlagsPtr[settings->courseId] |= flag; @@ -3387,9 +3441,9 @@ void obj_loop_goldenballoon(Object *obj, s32 updateRate) { sound_play_spatial(SOUND_COLLECT_BALLOON, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, NULL); obj->properties.npc.timer = 16; - obj->unk74 = 2; + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_2; obj->segment.trans.flags |= OBJ_FLAGS_INVISIBLE; - func_800AFC3C(obj, updateRate); + obj_spawn_particle(obj, updateRate); } } } @@ -3397,14 +3451,14 @@ void obj_loop_goldenballoon(Object *obj, s32 updateRate) { obj->segment.object.animationID = 0; obj64->forwardVel = 0.0f; speedf = (obj->segment.object.opacity < 255) ? 0 : 1; - if (obj64->unkD == 255) { - obj64->unkD = func_8001C524(obj->segment.trans.x_position, obj->segment.trans.y_position, - obj->segment.trans.z_position, 0); - if (obj64->unkD != 255) { - obj64->unkE = func_8001CC48(obj64->unkD, -1, 0); - obj64->unkF = func_8001CC48(obj64->unkE, obj64->unkD, 0); - obj64->unk10 = func_8001CC48(obj64->unkF, obj64->unkE, 0); - obj64->unkC = obj64->unkD; + if (obj64->nodeCurrent == 255) { + obj64->nodeCurrent = ainode_find_nearest(obj->segment.trans.x_position, obj->segment.trans.y_position, + obj->segment.trans.z_position, FALSE); + if (obj64->nodeCurrent != 255) { + obj64->nodeBack2 = func_8001CC48(obj64->nodeCurrent, -1, 0); + obj64->nodeForward1 = func_8001CC48(obj64->nodeBack2, obj64->nodeCurrent, 0); + obj64->nodeForward2 = func_8001CC48(obj64->nodeForward1, obj64->nodeBack2, 0); + obj64->nodeBack1 = obj64->nodeCurrent; } } else { func_8001C6C4((Object_64 *) obj64, obj, updateRateF, speedf, 0); @@ -3413,38 +3467,42 @@ void obj_loop_goldenballoon(Object *obj, s32 updateRate) { } } +/** + * Door init func. + * Sets all door parameters, which include type, direction and number of balloons needed to open + */ void obj_init_door(Object *obj, LevelObjectEntry_Door *entry) { Object_Door *door; f32 radius; door = &obj->unk64->door; - if (entry->unkC == -1) { - entry->unkC = func_8000CC20(obj); + if (entry->doorID == -1) { + entry->doorID = func_8000CC20(obj); } else { - func_8000CBF0(obj, entry->unkC); + func_8000CBF0(obj, entry->doorID); } - door->unkE = entry->unkC; - door->unkF = entry->unkE; - door->unk11 = entry->numBalloonsToOpen; - door->unk10 = entry->numBalloonsToOpen; - door->unk12 = entry->distanceToOpen; - if (door->unkE == -1) { + door->doorID = entry->doorID; + door->doorType = entry->doorType; + door->balloonCountUnused = entry->balloonCount; + door->balloonCount = entry->balloonCount; + door->radius = entry->distanceToOpen; + if (door->doorID == -1) { rmonPrintf("Illegal door no!!!\n"); } obj->segment.object.modelIndex = entry->modelIndex; obj->segment.trans.y_rotation = U8_ANGLE_TO_U16(entry->closedRotation); door->homeY = obj->segment.trans.y_position; - door->unk8 = 0; + door->jingleTimer = 0; obj->properties.door.closeAngle = obj->segment.trans.y_rotation; - obj->properties.door.openAngle = (s32) ((entry->openRotation & 0x3F) << 10); + obj->properties.door.openAngle = (entry->openRotation & 0x3F) << 10; radius = entry->scale & 0xFF; if (radius < 10.0f) { radius = 10.0f; } radius /= 64; obj->segment.trans.scale = obj->segment.header->scale * radius; - door->unk13 = (u8) entry->unkF; - door->unk14[0] = (s8) entry->unk11; + door->textID = entry->textID; + door->keyID = entry->keyID; obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0020; obj->interactObj->unk11 = 2; obj->interactObj->hitboxRadius = 20; @@ -3454,12 +3512,17 @@ void obj_init_door(Object *obj, LevelObjectEntry_Door *entry) { } } +/** + * Door loop func. + * If the requirement to open the door is not met, play a jingle and show a message. + * Since there's a number of different kinds of doors, this code handles each type. + */ void obj_loop_door(Object *doorObj, s32 updateRate) { - s32 temp2; - s16 temp; - volatile s32 sp54; // ??? - s32 sp50; - s32 sp4C; + s32 playSound; + s16 angleVel; + volatile s32 doorIDFlag; // ??? + s32 dist; + s32 keyBits; Object_Racer *racer; Object_Door *door; Settings *settings; @@ -3467,7 +3530,7 @@ void obj_loop_door(Object *doorObj, s32 updateRate) { ObjectInteraction *racerObjInter; LevelObjectEntry_Door *doorEntry; f32 updateRateF; - UNUSED s32 pad; + s32 model; s32 sp28; doorEntry = &doorObj->segment.level_entry->door; @@ -3476,92 +3539,92 @@ void obj_loop_door(Object *doorObj, s32 updateRate) { updateRateF *= 1.2; } settings = get_settings(); - temp2 = settings->courseFlagsPtr[settings->courseId]; + playSound = settings->courseFlagsPtr[settings->courseId]; door = &doorObj->unk64->door; - if (door->unkE >= 0) { - sp54 = 0x10000 << door->unkE; + if (door->doorID >= 0) { + doorIDFlag = 0x10000 << door->doorID; racerObjInter = doorObj->interactObj; - sp50 = racerObjInter->distance; - if (!(door->unkF & 1)) { - sp50 = 0; + dist = racerObjInter->distance; + if (!(door->doorType & 1)) { + dist = 0; // Door is forced open } - sp28 = temp2 & sp54; - if (sp28 == 0 && racerObjInter->distance < door->unk12) { + sp28 = playSound & doorIDFlag; + if (sp28 == 0 && racerObjInter->distance < door->radius) { racerObj = racerObjInter->obj; if (racerObj != NULL && racerObj->segment.header->behaviorId == BHV_RACER) { racer = &racerObj->unk64->racer; if (racer->playerIndex != PLAYER_COMPUTER && racerObj == doorObj->unk5C->unk100) { - if (door->unk13 != -1 && func_800C3400() == 0 && door->unkA == 0) { + if (door->textID != -1 && textbox_visible() == FALSE && door->jingleCooldown == 0) { music_fade(-8); - door->unk8 = 140; + door->jingleTimer = 140; // PAL users once again forsaken. music_jingle_voicelimit_set(16); - func_80008140(); + audioline_off(); music_jingle_play(SEQUENCE_NO_TROPHY_FOR_YOU); - set_textbox_display_value(door->unk10); - set_current_text(door->unk13 & 0xFF); + set_textbox_display_value(door->balloonCount); + set_current_text(door->textID & 0xFF); } - door->unkA = 300; + door->jingleCooldown = 300; } - if (func_800C3400() != 0) { - door->unkA = 300; + if (textbox_visible()) { + door->jingleCooldown = 300; } } } - if (door->unk8 != 0 && music_jingle_playing() == SEQUENCE_NONE) { - if (updateRate < door->unk8) { - door->unk8 -= updateRate; + if (door->jingleTimer != 0 && music_jingle_playing() == SEQUENCE_NONE) { + if (updateRate < door->jingleTimer) { + door->jingleTimer -= updateRate; } else { - door->unk8 = 0; + door->jingleTimer = 0; music_fade(8); music_jingle_voicelimit_set(6); - func_80008168(); + audioline_on(); } } - if (door->unkA > 0) { - door->unkA -= updateRate; + if (door->jingleCooldown > 0) { + door->jingleCooldown -= updateRate; } else { - door->unkA = 0; + door->jingleCooldown = 0; } racerObjInter = doorObj->interactObj; - sp4C = 0; - if (racerObjInter->distance < door->unk12) { + keyBits = 0; + if (racerObjInter->distance < door->radius) { racerObj = racerObjInter->obj; if (racerObj != NULL && racerObj->segment.header->behaviorId == BHV_RACER) { racer = &racerObj->unk64->racer; switch (racer->vehicleID) { case VEHICLE_HOVERCRAFT: - sp4C = 2; + keyBits = 2; break; case VEHICLE_PLANE: - sp4C = 4; + keyBits = 4; break; default: - sp4C = 1; + keyBits = 1; break; } } } - sp4C &= doorEntry->unk10; + keyBits &= doorEntry->unk10; if (doorEntry->common.objectID == ASSET_OBJECT_ID_BIGBOSSDOOR || doorEntry->common.objectID == ASSET_OBJECT_ID_BOSSDOOR) { - if (func_800235C0() != 0) { - sp50 = 0; + if (obj_door_override()) { + dist = 0; } } - if (door->unk14[1] == 0) { - if (sp4C == 0 && sp28 != 0 && sp50 < door->unk12) { - door->unk14[1] = 1; - } else if (door->unk12 + 10 < sp50) { - door->unk14[1] = -1; + if (door->openDir == DOOR_CLOSED) { + if (keyBits == 0 && sp28 != 0 && dist < door->radius) { + door->openDir = DOOR_OPENING; + } else if (door->radius + 10 < dist) { + door->openDir = DOOR_CLOSING; } } - temp2 = 0; - if (door->unkF & 2) { + playSound = FALSE; + if (door->doorType & 2) { if (sp28 != 0 && doorEntry->common.objectID == ASSET_OBJECT_ID_LEVELDOOR) { - if (settings->courseFlagsPtr[doorEntry->unk14] & 2) { + if (settings->courseFlagsPtr[doorEntry->levelID] & RACE_CLEARED) { if (settings->worldId == WORLD_FUTURE_FUN_LAND || settings->bosses & (1 << settings->worldId)) { - door->unk10 = doorEntry->unk15; - if (door->unk10 >= 10) { + door->balloonCount = doorEntry->balloonCountOverride; + if (door->balloonCount >= 10) { doorObj->segment.object.modelIndex = 3; } else { doorObj->segment.object.modelIndex = 2; @@ -3570,19 +3633,19 @@ void obj_loop_door(Object *doorObj, s32 updateRate) { doorObj->segment.object.modelIndex = 0; } } - if (settings->courseFlagsPtr[doorEntry->unk14] & 4) { + if (settings->courseFlagsPtr[doorEntry->levelID] & RACE_CLEARED_SILVER_COINS) { doorObj->segment.object.modelIndex = 1; } } - if (door->unk14[1] == 1) { - if (doorObj->segment.trans.y_position < (door->homeY + 130.0)) { - temp2 = 1; + if (door->openDir == DOOR_OPENING) { + if (doorObj->segment.trans.y_position < door->homeY + 130.0) { + playSound = TRUE; doorObj->segment.trans.y_position += 2.0 * updateRateF; } - } else if (door->unk14[1] == -1) { + } else if (door->openDir == DOOR_CLOSING) { if (door->homeY < doorObj->segment.trans.y_position) { - temp2 = 1; - doorObj->segment.trans.y_position -= (2.0 * updateRateF); + playSound = TRUE; + doorObj->segment.trans.y_position -= 2.0 * updateRateF; } } } else { @@ -3596,60 +3659,60 @@ void obj_loop_door(Object *doorObj, s32 updateRate) { if (settings->bosses & (1 << (settings->worldId + 6))) { doorObj->segment.object.modelIndex = 2; } - if (settings->worldId == 5) { - temp = doorObj->segment.object.modelIndex; - if (temp < 2) { - doorObj->segment.object.modelIndex = temp + 1; + if (settings->worldId == WORLD_FUTURE_FUN_LAND) { + model = doorObj->segment.object.modelIndex; + if (model < 2) { + doorObj->segment.object.modelIndex = model + 1; } } } - temp = 0; - if (door->unk14[1] == 1) { - temp = doorObj->segment.trans.y_rotation - doorObj->properties.common.unk4; - } else if (door->unk14[1] == -1) { - temp = doorObj->segment.trans.y_rotation - doorObj->properties.common.unk0; + angleVel = 0; + if (door->openDir == DOOR_OPENING) { + angleVel = doorObj->segment.trans.y_rotation - doorObj->properties.common.unk4; + } else if (door->openDir == DOOR_CLOSING) { + angleVel = doorObj->segment.trans.y_rotation - doorObj->properties.common.unk0; } - temp >>= 3; - if (temp > 0x200) { - temp = 0x200; + angleVel >>= 3; + if (angleVel > 0x200) { + angleVel = 0x200; } - if (temp < -0x200) { - temp = -0x200; + if (angleVel < -0x200) { + angleVel = -0x200; } - doorObj->segment.trans.y_rotation -= temp; //@!Delta - if (temp != 0) { - temp2 = 1; + doorObj->segment.trans.y_rotation -= angleVel; //@!Delta + if (angleVel != 0) { + playSound = TRUE; } } - if (temp2) { - if (door->unk4 == NULL) { + if (playSound) { + if (door->soundMask == NULL) { play_sound_at_position(SOUND_DOOR_OPEN, doorObj->segment.trans.x_position, doorObj->segment.trans.y_position, doorObj->segment.trans.z_position, 1, - &door->unk4); + &door->soundMask); } } else { - door->unk14[1] = 0; - if (door->unk4 != NULL) { - func_800096F8((SoundMask *) (s32) door->unk4); - door->unk4 = NULL; + door->openDir = DOOR_CLOSED; + if (door->soundMask != NULL) { + func_800096F8((SoundMask *) (s32) door->soundMask); + door->soundMask = NULL; } } - if (door->unk14[0] >= 0) { - sp4C = (1 << door->unk14[0]); - if (settings->keys & sp4C) { - settings->courseFlagsPtr[settings->courseId] |= sp54; + if (door->keyID >= 0) { + keyBits = 1 << door->keyID; + if (settings->keys & keyBits) { + settings->courseFlagsPtr[settings->courseId] |= doorIDFlag; } } else { - if (doorEntry->unk13 == 0) { - if (*settings->balloonsPtr >= door->unk10) { - settings->courseFlagsPtr[settings->courseId] |= sp54; + if (doorEntry->localBalloons == FALSE) { + if (*settings->balloonsPtr >= door->balloonCount) { + settings->courseFlagsPtr[settings->courseId] |= doorIDFlag; } else { - settings->courseFlagsPtr[settings->courseId] &= ~sp54; + settings->courseFlagsPtr[settings->courseId] &= ~doorIDFlag; } - } else if (settings->balloonsPtr[settings->worldId] >= door->unk10) { - settings->courseFlagsPtr[settings->courseId] |= sp54; + } else if (settings->balloonsPtr[settings->worldId] >= door->balloonCount) { + settings->courseFlagsPtr[settings->courseId] |= doorIDFlag; } else { - settings->courseFlagsPtr[settings->courseId] &= ~sp54; + settings->courseFlagsPtr[settings->courseId] &= ~doorIDFlag; } } } @@ -3660,21 +3723,25 @@ void obj_loop_door(Object *doorObj, s32 updateRate) { doorObj->unk5C->unk100 = NULL; } +/** + * T.T Door init func. + * A much simpler version of the regular door, but has many of the same attributes. + */ void obj_init_ttdoor(Object *obj, LevelObjectEntry_TTDoor *entry) { - Object_TTDoor *obj64; + Object_Door *obj64; f32 radius; obj->segment.object.modelIndex = 0; - obj64 = &obj->unk64->tt_door; + obj64 = &obj->unk64->door; obj->segment.trans.y_rotation = U8_ANGLE_TO_U16(entry->angleY); - obj64->doorID = entry->doorID; - obj64->unk13 = entry->unkB; + obj64->doorType = entry->doorType; + obj64->textID = entry->textID; obj64->homeY = obj->segment.trans.y_position; - obj64->unk8 = 0; - obj64->unk12 = entry->unkA; + obj64->jingleTimer = 0; + obj64->radius = entry->radius; obj->properties.door.closeAngle = obj->segment.trans.y_rotation; obj->properties.door.openAngle = (entry->unk9 & 0x3F) << 0xA; - radius = entry->radius & 0xFF; + radius = entry->scale & 0xFF; if (radius < 10) { radius = 10; } @@ -3696,54 +3763,54 @@ void obj_init_ttdoor(Object *obj, LevelObjectEntry_TTDoor *entry) { */ void obj_loop_ttdoor(Object *obj, s32 updateRate) { Settings *settings; - Object_TTDoor *ttDoor; + Object_Door *ttDoor; Object *racerObj; Object_Racer *racer; s16 angle; s32 openDoor; - ttDoor = (Object_TTDoor *) obj->unk64; + ttDoor = (Object_Door *) obj->unk64; settings = get_settings(); - if (ttDoor->doorID == 0) { + if (ttDoor->doorType == 0) { obj->segment.object.modelIndex = D_800DCA94[settings->ttAmulet]; } else { obj->segment.object.modelIndex = D_800DCA9C[settings->ttAmulet]; } - if (obj->interactObj->distance < ttDoor->unk12 && (settings->ttAmulet < 4 || *settings->balloonsPtr < 47)) { + if (obj->interactObj->distance < ttDoor->radius && (settings->ttAmulet < 4 || *settings->balloonsPtr < 47)) { racerObj = obj->interactObj->obj; if (racerObj != NULL && racerObj->segment.header->behaviorId == BHV_RACER) { racer = (Object_Racer *) racerObj->unk64; if (racer->playerIndex != PLAYER_COMPUTER && racerObj == obj->unk5C->unk100) { - if (ttDoor->unk13 != -1 && func_800C3400() == 0 && ttDoor->unkC == 0) { + if (ttDoor->textID != -1 && textbox_visible() == 0 && ttDoor->jingleCooldown == 0) { music_fade(-8); - ttDoor->unk8 = 140; + ttDoor->jingleTimer = 140; music_jingle_voicelimit_set(16); music_jingle_play(SEQUENCE_NO_TROPHY_FOR_YOU); - set_current_text(ttDoor->unk13 & 0xFF); + set_current_text(ttDoor->textID & 0xFF); } - ttDoor->unkC = 300; + ttDoor->jingleCooldown = 300; } - if (func_800C3400() != 0) { - ttDoor->unkC = 300; + if (textbox_visible()) { + ttDoor->jingleCooldown = 300; } } } - if (ttDoor->unk8 && music_jingle_playing() == SEQUENCE_NONE) { - if (updateRate < ttDoor->unk8) { - ttDoor->unk8 -= updateRate; + if (ttDoor->jingleTimer && music_jingle_playing() == SEQUENCE_NONE) { + if (updateRate < ttDoor->jingleTimer) { + ttDoor->jingleTimer -= updateRate; } else { - ttDoor->unk8 = 0.0f; + ttDoor->jingleTimer = 0.0f; music_fade(8); music_jingle_voicelimit_set(6); } } - if (ttDoor->unkC > 0) { - ttDoor->unkC -= updateRate; + if (ttDoor->jingleCooldown > 0) { + ttDoor->jingleCooldown -= updateRate; } else { - ttDoor->unkC = 0; + ttDoor->jingleCooldown = 0; } openDoor = TRUE; - if (settings->ttAmulet >= 4 && obj->interactObj->distance < ttDoor->unk12 && *settings->balloonsPtr >= 47) { + if (settings->ttAmulet >= 4 && obj->interactObj->distance < ttDoor->radius && *settings->balloonsPtr >= 47) { angle = obj->segment.trans.y_rotation - obj->properties.door.openAngle; } else { angle = obj->segment.trans.y_rotation - obj->properties.door.closeAngle; @@ -3866,16 +3933,20 @@ void obj_loop_trigger(Object *obj, UNUSED s32 updateRate) { } } +/** + * Moving Bridge init func. + * Sets hitbox info and the model from spawn info. + */ void obj_init_bridge_whaleramp(Object *obj, LevelObjectEntry_Bridge_WhaleRamp *entry) { - Object_Bridge_WhaleRamp *temp = &obj->unk64->bridge_whale_ramp; + Object_Bridge_WhaleRamp *bridge = &obj->unk64->bridge_whale_ramp; obj->segment.object.modelIndex = entry->modelIndex; obj->segment.trans.y_rotation = U8_ANGLE_TO_U16(entry->angleY); - temp->unk0 = obj->segment.trans.y_position; + bridge->homeY = obj->segment.trans.y_position; obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0020; obj->interactObj->unk11 = 2; obj->interactObj->hitboxRadius = 20; obj->interactObj->pushForce = 0; - temp->unk4 = 0; + bridge->soundMask = NULL; if (obj->segment.object.modelIndex >= obj->segment.header->numberOfModelIds) { obj->segment.object.modelIndex = 0; } @@ -3890,17 +3961,17 @@ void obj_init_bridge_whaleramp(Object *obj, LevelObjectEntry_Bridge_WhaleRamp *e void obj_loop_bridge_whaleramp(Object *obj, s32 updateRate) { Object *racerObj; UNUSED ObjectTransform *temp_v0_4; - f32 temp_f2; + f32 bobAmount; Object_Bridge_WhaleRamp *whaleRamp; LevelObjectEntry_Bridge_WhaleRamp *entry; f32 updateRateF; s32 vehicleID; - f32 sp50; - f32 sp4C; - f32 sp48; - f32 sp44; - f32 sp40; - f32 sp3C; + f32 bellX1; + f32 bellY1; + f32 bellZ1; + f32 bellX2; + f32 bellY2; + f32 bellZ2; Object_Racer *racer; whaleRamp = (Object_Bridge_WhaleRamp *) obj->unk64; @@ -3913,46 +3984,44 @@ void obj_loop_bridge_whaleramp(Object *obj, s32 updateRate) { if (entry->unkB != 3) { if (obj->properties.common.unk0 != 0) { - temp_f2 = (2.0 * (f32) entry->unkE); - if (temp_f2 > 0.0f) { - if (obj->segment.trans.y_position < (whaleRamp->unk0 + temp_f2)) { - obj->segment.trans.y_position += (updateRateF * 2); + bobAmount = 2.0 * (f32) entry->bobAmount; + if (bobAmount > 0.0f) { + if (obj->segment.trans.y_position < whaleRamp->homeY + bobAmount) { + obj->segment.trans.y_position += updateRateF * 2; } } else { - if ((whaleRamp->unk0 + temp_f2) < obj->segment.trans.y_position) { - obj->segment.trans.y_position -= (updateRateF * 2); + if (whaleRamp->homeY + bobAmount < obj->segment.trans.y_position) { + obj->segment.trans.y_position -= updateRateF * 2; } } } else if (entry->radius > 0) { - if (whaleRamp->unk0 < obj->segment.trans.y_position) { - obj->segment.trans.y_position -= (updateRateF * 2); + if (whaleRamp->homeY < obj->segment.trans.y_position) { + obj->segment.trans.y_position -= updateRateF * 2; } } else { - if (obj->segment.trans.y_position < whaleRamp->unk0) { - obj->segment.trans.y_position += (updateRateF * 2); + if (obj->segment.trans.y_position < whaleRamp->homeY) { + obj->segment.trans.y_position += updateRateF * 2; } } } else if (obj->properties.common.unk0 != 0) { if (obj->segment.trans.x_rotation >= -0x12FF) { - obj->segment.trans.x_rotation -= (updateRate * 0x2D); + obj->segment.trans.x_rotation -= updateRate * 0x2D; } - if (whaleRamp->unk4 == 0) { - whaleRamp = whaleRamp; - func_8001E36C(entry->unkA, &sp50, &sp4C, &sp48); - play_sound_at_position(SOUND_DRAWBRIDGE_BELL, sp50, sp4C, sp48, 1, &whaleRamp->unk4); + if (whaleRamp->soundMask == NULL) { + obj_bridge_pos(entry->unkA, &bellX1, &bellY1, &bellZ1); + play_sound_at_position(SOUND_DRAWBRIDGE_BELL, bellX1, bellY1, bellZ1, 1, &whaleRamp->soundMask); } } else { if (obj->segment.trans.x_rotation < 0) { - obj->segment.trans.x_rotation = obj->segment.trans.x_rotation + (updateRate * 0x28); - if (whaleRamp->unk4 == 0) { - whaleRamp = whaleRamp; - func_8001E36C(entry->unkA, &sp44, &sp40, &sp3C); - play_sound_at_position(SOUND_DRAWBRIDGE_BELL, sp44, sp40, sp3C, 1, &whaleRamp->unk4); + obj->segment.trans.x_rotation += updateRate * 0x28; + if (whaleRamp->soundMask == NULL) { + obj_bridge_pos(entry->unkA, &bellX2, &bellY2, &bellZ2); + play_sound_at_position(SOUND_DRAWBRIDGE_BELL, bellX2, bellY2, bellZ2, 1, &whaleRamp->soundMask); } } else { obj->segment.trans.x_rotation = 0; - if (whaleRamp->unk4 != NULL) { - func_800096F8(whaleRamp->unk4); + if (whaleRamp->soundMask != NULL) { + func_800096F8(whaleRamp->soundMask); } } } @@ -4054,14 +4123,22 @@ void obj_loop_skycontrol(Object *obj, UNUSED s32 updateRate) { } } +/** + * AI node init func. + * Adds itself to the node list, and then tells the game AI nodes exist. + */ void obj_init_ainode(Object *obj, LevelObjectEntry_AiNode *entry) { - if (entry->unk9 == 0xFF) { - entry->unk9 = func_8001C48C(obj) & 0xFF; + if (entry->nodeID == NODE_NONE) { + entry->nodeID = ainode_register(obj) & NODE_NONE; } - func_8001D1BC(entry->unk9); - func_8001D1AC(); + ainode_tail_set(entry->nodeID); + ainode_enable(); } +/** + * AI node loop func. + * Does nothing. All the relevant behaviour is handled globally. + */ void obj_loop_ainode(UNUSED Object *obj, UNUSED s32 updateRate) { } @@ -4139,10 +4216,17 @@ void obj_loop_treasuresucker(Object *obj, s32 updateRate) { } } +/** + * Smokey's Castle Treasure Visual init func. + */ void obj_init_flycoin(UNUSED Object *obj, UNUSED LevelObjectEntry_FlyCoin *entry) { } -// Smokey's castle banana pickups. +/** + * Smokey's Castle Treasure Visual loop func. + * When spawned, moves with the velocity given, which makes it aim towards the treasure box. + * Deletes itself once the timer hits zero. Will also trigger the win condition once necessary. + */ void obj_loop_flycoin(Object *obj, s32 updateRate) { f32 updateRateF; Object_Racer *racerObj; @@ -4169,10 +4253,18 @@ void obj_loop_flycoin(Object *obj, s32 updateRate) { obj->segment.animFrame += updateRate * 8; } +/** + * Smokey's Castle Banana Spawner init func. + * Seemingly does nothing. + */ void obj_init_bananacreator(Object *obj, UNUSED LevelObjectEntry_BananaCreator *entry) { obj->segment.animFrame = 100; } +/** + * Smokey's Castle Banana Spawner loop func. + * Spawns a banana. If it is collected, then it will spawn another 20 seconds later. + */ void obj_loop_bananacreator(Object *obj, s32 updateRate) { LevelObjectEntryCommon newEntry; Object *newBananaObj; @@ -4183,9 +4275,9 @@ void obj_loop_bananacreator(Object *obj, s32 updateRate) { } if (obj->properties.bananaSpawner.timer <= 0) { - newEntry.x = (s32) obj->segment.trans.x_position; - newEntry.y = ((s32) ((s16) obj->segment.trans.y_position)) - 3; - newEntry.z = (s32) obj->segment.trans.z_position; + newEntry.x = obj->segment.trans.x_position; + newEntry.y = (s16) obj->segment.trans.y_position - 3; + newEntry.z = obj->segment.trans.z_position; newEntry.size = 8; newEntry.objectID = ASSET_OBJECT_ID_COIN; newBananaObj = spawn_object(&newEntry, 1); @@ -4198,16 +4290,22 @@ void obj_loop_bananacreator(Object *obj, s32 updateRate) { obj->segment.trans.z_position, ASSET_OBJECT_ID_BOMBEXPLOSION, SOUND_SELECT, 0.25f, 0); obj->properties.bananaSpawner.spawn = FALSE; } - obj->properties.bananaSpawner.timer = TIME_SECONDS(20); // Set delay to respawn banana to 20 seconds. + // Set respawn timer 20 seconds. Poor PAL users aren't accounted for, and must wait 24 seconds. + obj->properties.bananaSpawner.timer = TIME_SECONDS(20); } } +/** + * Banana init func. + * Sets the interaction properties. + * If bananas are disabled, then delete itself. + */ void obj_init_banana(Object *obj, UNUSED LevelObjectEntry_Banana *entry) { obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; obj->interactObj->hitboxRadius = 30; - obj->properties.banana.unk4 = 20; - obj->properties.banana.unk6 = 16; + obj->properties.banana.intangibleTimer = 20; // PAL users doomed to wait 24 frames. + obj->properties.banana.destroyTimer = 16; if (get_filtered_cheats() & CHEAT_DISABLE_BANANAS) { free_object(obj); } @@ -4227,7 +4325,7 @@ void obj_loop_banana(Object *obj, s32 updateRate) { f32 velX; f32 velZ; s32 sp48; - s32 sp44; + s32 hitDist; s8 sp43; Object_Banana *banana; ObjPropertyBanana *properties; @@ -4240,12 +4338,12 @@ void obj_loop_banana(Object *obj, s32 updateRate) { banana = (Object_Banana *) obj->unk64; obj->segment.animFrame += updateRate * 8; properties = (ObjPropertyBanana *) &obj->properties.banana; - if (properties->unk0 == -1) { + if (properties->status == BANANA_COLLECTED) { obj->segment.trans.flags |= OBJ_FLAGS_INVISIBLE; - properties->unk6 -= updateRate; - obj->unk74 = 1; - func_800AFC3C(obj, updateRate); - if (properties->unk6 <= 0) { + properties->destroyTimer -= updateRate; + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; + obj_spawn_particle(obj, updateRate); + if (properties->destroyTimer <= 0) { free_object(obj); } } else { @@ -4255,7 +4353,7 @@ void obj_loop_banana(Object *obj, s32 updateRate) { banana->unk8 = 0; banana->unk0 = 0; } - if (properties->unk0 == 1) { + if (properties->status == BANANA_DROPPED) { tempPos[0] = obj->segment.trans.x_position + (obj->segment.x_velocity * updateRateF); tempPos[1] = obj->segment.trans.y_position + (obj->segment.y_velocity * updateRateF); tempPos[2] = obj->segment.trans.z_position + (obj->segment.z_velocity * updateRateF); @@ -4269,10 +4367,11 @@ void obj_loop_banana(Object *obj, s32 updateRate) { obj->segment.trans.x_position = tempPos[0]; obj->segment.trans.y_position = tempPos[1]; obj->segment.trans.z_position = tempPos[2]; - if (banana->unk9 != 2) { - obj->segment.y_velocity -= 1.0; - obj->segment.x_velocity *= 0.95; - obj->segment.z_velocity *= 0.95; + // Bananas dropped by planes will not have gravity. + if (banana->droppedVehicleID != VEHICLE_PLANE) { + obj->segment.y_velocity -= 1.0; //!@Delta + obj->segment.x_velocity *= 0.95; //!@Delta + obj->segment.z_velocity *= 0.95; //!@Delta } else { obj->segment.x_velocity = 0.0f; obj->segment.y_velocity = 0.0f; @@ -4287,23 +4386,23 @@ void obj_loop_banana(Object *obj, s32 updateRate) { velZ = -velZ; } if (sp48 > 0 && velX < 0.5 && velZ < 0.5) { - properties->unk0 = 0; + properties->status = BANANA_IDLE; } radius = -10000.0f; if (func_8002B9BC(obj, &radius, NULL, 1) != 0 && obj->segment.trans.y_position < radius) { - properties->unk0 = 0; + properties->status = BANANA_IDLE; obj->segment.trans.y_position = radius; } } - sp44 = 70; - if (banana->unk9 != 2) { - sp44 = 55; + hitDist = 70; + if (banana->droppedVehicleID != VEHICLE_PLANE) { + hitDist = 55; // Non-planes have smaller hitboxes. } - if (properties->unk4 > 0) { - properties->unk4 -= updateRate; + if (properties->intangibleTimer > 0) { + properties->intangibleTimer -= updateRate; } else { - properties->unk4 = 0; + properties->intangibleTimer = 0; } if (obj->interactObj->distance < 120) { if (get_current_level_race_type() == RACETYPE_CHALLENGE_BANANAS) { @@ -4311,16 +4410,16 @@ void obj_loop_banana(Object *obj, s32 updateRate) { if (racerObj != NULL && racerObj->segment.header->behaviorId == BHV_RACER) { racer = (Object_Racer *) racerObj->unk64; if (racer->playerIndex == PLAYER_COMPUTER) { - sp44 += 30; + hitDist += 30; // AI players are offered extra courtesy. } } } } - if (obj->interactObj->distance < sp44 && properties->unk4 == 0) { + if (obj->interactObj->distance < hitDist && properties->intangibleTimer == 0) { racerObj = obj->interactObj->obj; if (racerObj != NULL && racerObj->segment.header->behaviorId == BHV_RACER) { racer = (Object_Racer *) racerObj->unk64; - if ((get_current_level_race_type() != RACETYPE_CHALLENGE_BANANAS) || racer->bananas < 2) { + if (get_current_level_race_type() != RACETYPE_CHALLENGE_BANANAS || racer->bananas < 2) { prevSoundMask = racer->bananaSoundMask; play_sound_at_position(SOUND_SELECT, racerObj->segment.trans.x_position, racerObj->segment.trans.y_position, racerObj->segment.trans.z_position, 4, @@ -4340,9 +4439,9 @@ void obj_loop_banana(Object *obj, s32 updateRate) { if (get_number_of_active_players() > TWO_PLAYERS) { free_object(obj); } else { - properties->unk0 = -1; - obj->unk74 = 1; - func_800AFC3C(obj, updateRate); + properties->status = BANANA_COLLECTED; + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; + obj_spawn_particle(obj, updateRate); } } } @@ -4435,8 +4534,8 @@ void obj_loop_silvercoin(Object *obj, s32 updateRate) { } if (obj->properties.npc.timer > 0) { obj->properties.npc.timer -= updateRate; - obj->unk74 = 1; - func_800AFC3C(obj, updateRate); + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; + obj_spawn_particle(obj, updateRate); } } @@ -4499,7 +4598,7 @@ void obj_loop_worldkey(Object *worldKeyObj, s32 updateRate) { void obj_init_weaponballoon(Object *obj, LevelObjectEntry_WeaponBalloon *entry) { s32 cheats; Object_WeaponBalloon *balloon; - f32 radius; + f32 scale; obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 4; @@ -4531,24 +4630,29 @@ void obj_init_weaponballoon(Object *obj, LevelObjectEntry_WeaponBalloon *entry) obj->segment.object.modelIndex = entry->balloonType; obj->properties.weaponBalloon.balloonID = obj->segment.object.modelIndex; - radius = entry->radius & 0xFF; - if (radius < 10) { - radius = 10; + scale = entry->scale & 0xFF; + if (scale < 10) { + scale = 10; } - radius /= 64; + scale /= 64; balloon = &obj->unk64->weapon_balloon; - obj->segment.trans.scale = obj->segment.header->scale * radius; - balloon->radius = obj->segment.trans.scale; - balloon->unk4 = 0; - obj->properties.weaponBalloon.unk4 = 0; + obj->segment.trans.scale = obj->segment.header->scale * scale; + balloon->scale = obj->segment.trans.scale; + balloon->respawnTime = 0; + obj->properties.weaponBalloon.particleTimer = 0; if (get_filtered_cheats() & CHEAT_DISABLE_WEAPONS) { free_object(obj); } } +/** + * Weapon Balloon loop func. + * Checks for any racers going over it. + * It gives them a weapon, then marks as disappeared, before slowly regrowing and becoming tangible again. + */ void obj_loop_weaponballoon(Object *weaponBalloonObj, s32 updateRate) { UNUSED s32 pad; Object_Racer *racer; @@ -4562,7 +4666,7 @@ void obj_loop_weaponballoon(Object *weaponBalloonObj, s32 updateRate) { s32 prevBalloonType; weaponBalloon = (Object_WeaponBalloon *) weaponBalloonObj->unk64; - weaponBalloonObj->segment.trans.scale = weaponBalloon->radius * (1.0 - (weaponBalloon->unk4 / 90.0f)); + weaponBalloonObj->segment.trans.scale = weaponBalloon->scale * (1.0 - (weaponBalloon->respawnTime / 90.0f)); if (weaponBalloonObj->segment.trans.scale < 0.001) { weaponBalloonObj->segment.trans.scale = 0.001f; } @@ -4571,17 +4675,17 @@ void obj_loop_weaponballoon(Object *weaponBalloonObj, s32 updateRate) { } else { weaponBalloonObj->segment.trans.flags &= ~OBJ_FLAGS_INVISIBLE; } - if (weaponBalloonObj->properties.weaponBalloon.unk4 > 0) { - weaponBalloonObj->unk74 = 1; - func_800AFC3C(weaponBalloonObj, updateRate); - weaponBalloonObj->properties.weaponBalloon.unk4 -= updateRate; + if (weaponBalloonObj->properties.weaponBalloon.particleTimer > 0) { + weaponBalloonObj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; + obj_spawn_particle(weaponBalloonObj, updateRate); + weaponBalloonObj->properties.weaponBalloon.particleTimer -= updateRate; } - if (weaponBalloon->unk4 != 0) { - if (weaponBalloon->unk4 != 90 || weaponBalloonObj->interactObj->distance >= 45) { - weaponBalloon->unk4 = (weaponBalloon->unk4 - updateRate) - updateRate; + if (weaponBalloon->respawnTime != 0) { + if (weaponBalloon->respawnTime != 90 || weaponBalloonObj->interactObj->distance >= 45) { + weaponBalloon->respawnTime = (weaponBalloon->respawnTime - updateRate) - updateRate; } - if (weaponBalloon->unk4 < 0) { - weaponBalloon->unk4 = 0; + if (weaponBalloon->respawnTime < 0) { + weaponBalloon->respawnTime = 0; } } else { interactObj = weaponBalloonObj->interactObj; @@ -4616,12 +4720,12 @@ void obj_loop_weaponballoon(Object *weaponBalloonObj, s32 updateRate) { racer->balloon_level = 2; levelMask = 2; } - powerupTable = (s8 *) get_misc_asset(ASSET_MISC_12); + powerupTable = (s8 *) get_misc_asset(ASSET_MISC_BALLOON_DATA); prevBalloonQuantity = racer->balloon_quantity; racer->balloon_quantity = powerupTable[(racer->balloon_type * 10) + (racer->balloon_level * 2) + 1]; racer->unk209 |= 1; if (get_number_of_active_players() < THREE_PLAYERS) { - weaponBalloonObj->properties.weaponBalloon.unk4 = 16; + weaponBalloonObj->properties.weaponBalloon.particleTimer = 16; } if (racer->playerIndex == PLAYER_COMPUTER) { play_sound_at_position(SOUND_BALLOON_POP, weaponBalloonObj->segment.trans.x_position, @@ -4651,9 +4755,9 @@ void obj_loop_weaponballoon(Object *weaponBalloonObj, s32 updateRate) { sound_play(SOUND_COLLECT_ITEM + racer->balloon_level, NULL); } } - weaponBalloonObj->unk74 = 1; - func_800AFC3C(weaponBalloonObj, updateRate); - weaponBalloon->unk4 = 90; + weaponBalloonObj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; + obj_spawn_particle(weaponBalloonObj, updateRate); + weaponBalloon->respawnTime = 90; } } } @@ -4698,13 +4802,13 @@ void obj_loop_weapon(Object *obj, s32 updateRate) { switch (weapon->weaponID) { case WEAPON_ROCKET_HOMING: case WEAPON_ROCKET: - handle_rocket_projectile(obj, updateRate); + weapon_projectile(obj, updateRate); break; case WEAPON_TRIPMINE: case WEAPON_OIL_SLICK: case WEAPON_BUBBLE_TRAP: case WEAPON_UNK_11: - func_8003F2E8(obj, updateRate); + weapon_trap(obj, updateRate); break; } return; @@ -4715,7 +4819,7 @@ void obj_loop_weapon(Object *obj, s32 updateRate) { * A homing rocket uses the checkpoint system to path towards its victim. * When it collides with a racer, they're launched into the air. */ -void handle_rocket_projectile(Object *obj, s32 updateRate) { +void weapon_projectile(Object *obj, s32 updateRate) { Object *interactObj; Object_Racer *weaponOwner; Object_Weapon *weapon; @@ -4968,8 +5072,8 @@ void homing_rocket_prevent_overshoot(Object *obj, s32 updateRate, Object_Weapon } play_rocket_trailing_sound(obj, rocket, SOUND_HOMING_ROCKET); if (get_number_of_active_players() < 3) { - obj->unk74 |= 1; - func_800AFC3C(obj, updateRate); + obj->particleEmitFlags |= OBJ_EMIT_PARTICLE_1; + obj_spawn_particle(obj, updateRate); } } @@ -5036,80 +5140,87 @@ void play_rocket_trailing_sound(Object *obj, struct Object_Weapon *weapon, u16 s } } -void func_8003F2E8(Object *weaponObj, s32 updateRate) { +/** + * Handles all the trap weapon behaviour. + * When dropped, will fall to the ground, provided the user wasn't in a plane. + * Once on the ground, will count up until it reaches the target and consider itself armed. + * The timer is used for scaling the trap, which the bubble and oil slick use. + * If triggered, the trap will perform different behaviours depending on what it is, then remove itself. + */ +void weapon_trap(Object *weaponObj, s32 updateRate) { Object *weaponInteractObj; Object_Racer *weaponHit; Object_Racer *weaponOwner; - Vec3f sp58; + Vec3f intendedPos; f32 radius; f32 updateRateF; s32 hasCollision; - s32 var_a1; + s32 hitDist; s8 surface; Object_Weapon *weapon; ObjPropertyWeapon *weaponProperties; weapon = &weaponObj->unk64->weapon; weaponOwner = &weapon->owner->unk64->racer; - updateRateF = (f32) updateRate; + updateRateF = updateRate; weaponProperties = &weaponObj->properties.weapon; if (osTvType == TV_TYPE_PAL) { updateRateF *= 1.2; } - if (weaponProperties->unk4 == 0) { - sp58.x = weaponObj->segment.trans.x_position + (weaponObj->segment.x_velocity * updateRateF); - sp58.y = weaponObj->segment.trans.y_position + (weaponObj->segment.y_velocity * updateRateF); - sp58.z = weaponObj->segment.trans.z_position + (weaponObj->segment.z_velocity * updateRateF); + if (weaponProperties->status == WEAPON_DROPPED) { + intendedPos.x = weaponObj->segment.trans.x_position + (weaponObj->segment.x_velocity * updateRateF); + intendedPos.y = weaponObj->segment.trans.y_position + (weaponObj->segment.y_velocity * updateRateF); + intendedPos.z = weaponObj->segment.trans.z_position + (weaponObj->segment.z_velocity * updateRateF); radius = 9.0f; - func_80031130(1, &weaponObj->segment.trans.x_position, &sp58.x, -1); + func_80031130(1, &weaponObj->segment.trans.x_position, &intendedPos.x, -1); hasCollision = FALSE; surface = -1; - func_80031600(&weaponObj->segment.trans.x_position, &sp58.x, &radius, &surface, 1, &hasCollision); - weaponObj->segment.x_velocity = (sp58.x - weaponObj->segment.trans.x_position) / updateRateF; - weaponObj->segment.y_velocity = (sp58.y - weaponObj->segment.trans.y_position) / updateRateF; - weaponObj->segment.z_velocity = (sp58.z - weaponObj->segment.trans.z_position) / updateRateF; - weaponObj->segment.trans.x_position = sp58.x; - weaponObj->segment.trans.y_position = sp58.y; - weaponObj->segment.trans.z_position = sp58.z; + func_80031600(&weaponObj->segment.trans.x_position, &intendedPos.x, &radius, &surface, 1, &hasCollision); + weaponObj->segment.x_velocity = (intendedPos.x - weaponObj->segment.trans.x_position) / updateRateF; + weaponObj->segment.y_velocity = (intendedPos.y - weaponObj->segment.trans.y_position) / updateRateF; + weaponObj->segment.z_velocity = (intendedPos.z - weaponObj->segment.trans.z_position) / updateRateF; + weaponObj->segment.trans.x_position = intendedPos.x; + weaponObj->segment.trans.y_position = intendedPos.y; + weaponObj->segment.trans.z_position = intendedPos.z; if (hasCollision || weaponOwner->vehicleID == VEHICLE_PLANE) { weaponObj->segment.x_velocity = 0.0f; weaponObj->segment.z_velocity = 0.0f; - weaponProperties->unk4 = 1; - weaponProperties->unk5 = 0; - weaponProperties->unk6 = 0; + weaponProperties->status = WEAPON_ARMED; + weaponProperties->submerged = 0; + weaponProperties->scale = 0; if (weapon->weaponID == WEAPON_BUBBLE_TRAP) { weaponObj->segment.trans.y_position += 16.0f; } } radius = -10000.0f; if (func_8002B9BC(weaponObj, &radius, NULL, 1) && (weaponObj->segment.trans.y_position < radius)) { - weaponProperties->unk4 = 1; - weaponProperties->unk5 = 1; - weaponProperties->unk6 = 0; + weaponProperties->status = WEAPON_ARMED; + weaponProperties->submerged = 1; + weaponProperties->scale = 0; if (weapon->weaponID == WEAPON_BUBBLE_TRAP) { weaponObj->segment.trans.y_position += 16.0f; } } } if (weapon->weaponID == WEAPON_OIL_SLICK) { - if (weaponProperties->unk4 != 0) { - if (weaponProperties->unk4 == 1) { - weaponProperties->unk6 += updateRate; - if (weaponProperties->unk6 > 12) { - weaponProperties->unk6 = 12; + if (weaponProperties->status != WEAPON_DROPPED) { + if (weaponProperties->status == WEAPON_ARMED) { + weaponProperties->scale += updateRate; + if (weaponProperties->scale > 12) { + weaponProperties->scale = 12; } } else { - weaponProperties->unk6 -= updateRate; - if (weaponProperties->unk6 <= 0) { - weaponProperties->unk6 = 1; + weaponProperties->scale -= updateRate; + if (weaponProperties->scale <= 0) { + weaponProperties->scale = 1; free_object(weaponObj); } } if (weaponOwner->vehicleID != VEHICLE_PLANE) { - if (weaponProperties->unk5 != 0) { - weaponObj->waterEffect->scale = weaponProperties->unk6 * 0.6f; + if (weaponProperties->submerged != 0) { + weaponObj->waterEffect->scale = weaponProperties->scale * 0.6f; } else { - weaponObj->shadow->scale = weaponProperties->unk6 * 0.6f; + weaponObj->shadow->scale = weaponProperties->scale * 0.6f; } weaponObj->segment.trans.flags |= OBJ_FLAGS_SHADOW_ONLY; } @@ -5124,16 +5235,16 @@ void func_8003F2E8(Object *weaponObj, s32 updateRate) { move_object(weaponObj, weapon->target->segment.trans.x_position, weapon->target->segment.trans.y_position, weapon->target->segment.trans.z_position); } - if (weaponProperties->unk4 == 1 || weaponProperties->unk4 == 2) { - weaponProperties->unk6 += updateRate; - if (weaponProperties->unk6 > 20) { - weaponProperties->unk6 = 20; + if (weaponProperties->status == WEAPON_ARMED || weaponProperties->status == WEAPON_TRIGGERED) { + weaponProperties->scale += updateRate; + if (weaponProperties->scale > 20) { + weaponProperties->scale = 20; } } - if (weaponProperties->unk4 == 2) { - weaponProperties->unk5 += updateRate; - if (weaponProperties->unk5 > 120) { - weaponProperties->unk4 = 3; + if (weaponProperties->status == WEAPON_TRIGGERED) { + weaponProperties->submerged += updateRate; + if (weaponProperties->submerged > 120) { + weaponProperties->status = WEAPON_DESTROY; if (weapon->soundMask != NULL) { func_800096F8(weapon->soundMask); weapon->soundMask = NULL; @@ -5143,25 +5254,25 @@ void func_8003F2E8(Object *weaponObj, s32 updateRate) { NULL); } } - if (weaponProperties->unk4 == 3) { - weaponObj->unk74 = 1; - func_800AFC3C(weaponObj, updateRate); + if (weaponProperties->status == WEAPON_DESTROY) { + weaponObj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; + obj_spawn_particle(weaponObj, updateRate); weaponObj->segment.trans.flags |= OBJ_FLAGS_INVISIBLE; - weaponProperties->unk6 -= updateRate; - if (weaponProperties->unk6 < 1) { - weaponProperties->unk6 = 1; + weaponProperties->scale -= updateRate; + if (weaponProperties->scale < 1) { + weaponProperties->scale = 1; free_object(weaponObj); } } - if (weaponProperties->unk4 != 0) { - weaponObj->segment.trans.scale = (f32) weaponProperties->unk6 * 0.075f; + if (weaponProperties->status != WEAPON_DROPPED) { + weaponObj->segment.trans.scale = weaponProperties->scale * 0.075f; } weaponObj->segment.animFrame += updateRate * 16; } - if (weaponProperties->unk4 < 2) { - var_a1 = 60; + if (weaponProperties->status < WEAPON_TRIGGERED) { + hitDist = 60; if (weaponOwner->vehicleID != VEHICLE_PLANE) { - var_a1 = 34; + hitDist = 34; weaponObj->segment.y_velocity -= 2.0; weaponObj->segment.x_velocity -= (weaponObj->segment.x_velocity / 8); weaponObj->segment.z_velocity -= (weaponObj->segment.z_velocity / 8); @@ -5170,12 +5281,12 @@ void func_8003F2E8(Object *weaponObj, s32 updateRate) { weaponObj->segment.animFrame += updateRate * 8; } if (weapon->weaponID == WEAPON_BUBBLE_TRAP || weapon->weaponID == WEAPON_OIL_SLICK) { - var_a1 += var_a1 >> 1; + hitDist += hitDist >> 1; } weaponInteractObj = weaponObj->interactObj->obj; if (weaponInteractObj != NULL) { - if (weapon->owner != weaponObj->interactObj->obj || weaponProperties->unk0 < normalise_time(450)) { - if (weaponObj->interactObj->distance < var_a1) { + if (weapon->owner != weaponObj->interactObj->obj || weaponProperties->decayTimer < normalise_time(450)) { + if (weaponObj->interactObj->distance < hitDist) { weaponInteractObj = weaponObj->interactObj->obj; if (weaponInteractObj->segment.header->behaviorId == BHV_RACER) { weaponHit = &weaponInteractObj->unk64->racer; @@ -5186,7 +5297,7 @@ void func_8003F2E8(Object *weaponObj, s32 updateRate) { SOUND_EXPLOSION, 1.0f, 1); } else if (weapon->weaponID == WEAPON_BUBBLE_TRAP) { if (weaponHit->shieldTimer > 0 && weaponHit->shieldType >= SHIELD_LEVEL3) { - weaponProperties->unk4 = 3; + weaponProperties->status = WEAPON_DESTROY; play_sound_at_position(SOUND_POP, weaponObj->segment.trans.x_position, weaponObj->segment.trans.y_position, @@ -5199,12 +5310,12 @@ void func_8003F2E8(Object *weaponObj, s32 updateRate) { weaponInteractObj->segment.trans.z_position, 4, &weapon->soundMask); weaponHit->attackType = ATTACK_BUBBLE; - weaponProperties->unk4 = 2; - weaponProperties->unk5 = 0; + weaponProperties->status = WEAPON_TRIGGERED; + weaponProperties->submerged = 0; } } else if (weapon->weaponID == WEAPON_OIL_SLICK) { weaponHit->attackType = ATTACK_SPIN; - weaponProperties->unk4 = 2; + weaponProperties->status = WEAPON_TRIGGERED; } if (!weaponHit->raceFinished) { rumble_set(weaponHit->playerIndex, RUMBLE_TYPE_13); @@ -5221,13 +5332,13 @@ void func_8003F2E8(Object *weaponObj, s32 updateRate) { } } } - weaponProperties->unk0 -= updateRate; - if (weaponProperties->unk4 < 2) { - if (weaponProperties->unk0 < normalise_time(-1320)) { + weaponProperties->decayTimer -= updateRate; + if (weaponProperties->status < WEAPON_TRIGGERED) { + if (weaponProperties->decayTimer < normalise_time(-1320)) { if (weapon->weaponID == WEAPON_OIL_SLICK) { - weaponProperties->unk4 = 2; + weaponProperties->status = WEAPON_TRIGGERED; } else if ((weapon->weaponID == WEAPON_BUBBLE_TRAP)) { - weaponProperties->unk4 = 3; + weaponProperties->status = WEAPON_DESTROY; play_sound_at_position(SOUND_POP, weaponObj->segment.trans.x_position, weaponObj->segment.trans.y_position, weaponObj->segment.trans.z_position, 4, NULL); @@ -5516,12 +5627,21 @@ void obj_loop_weather(Object *obj, UNUSED s32 updateRate) { } } +/** + * Lens Flare init func. + * Calls the function to initialise the lens flare system, using presets. + */ void obj_init_lensflare(Object *obj, UNUSED LevelObjectEntry_LensFlare *entry) { - func_800AC8A8(obj); + lensflare_init(obj); } +/** + * Lens Flare Override init func. + * Calls a function adding the object to the lens flare system, + * so the rendering portion knows to disable lens flares when inside. + */ void obj_init_lensflareswitch(Object *obj, LevelObjectEntry_LensFlareSwitch *entry, UNUSED s32 arg2) { - cameraAddOverrideObject(obj); + lensflare_override_add(obj); obj->segment.trans.scale = entry->radius; obj->segment.trans.scale /= 40.0f; } @@ -5646,18 +5766,23 @@ void obj_init_midichset(Object *obj, LevelObjectEntry_Midichset *entry) { /* Official name: bubblerInit */ void obj_init_bubbler(Object *obj, LevelObjectEntry_Bubbler *entry) { - func_800AF134((Particle *) obj->unk6C, entry->particleBehaviourID, entry->particlePropertyID, 0, 0, 0); - obj->properties.common.unk0 = entry->unkA; + func_800AF134((Particle *) obj->particleEmitter, entry->particleBehaviourID, entry->particlePropertyID, 0, 0, 0); + obj->properties.common.unk0 = entry->particleDensity; } +/** + * Bubbler Boss loop func. + * All the racer side is handled elsewhere. + * This rolls a random number and starts emitting particles based on that for variable density. + */ void obj_loop_bubbler(Object *obj, s32 updateRate) { if (obj->properties.common.unk0 >= get_random_number_from_range(0, 1024)) { - obj->unk74 = 1; + obj->particleEmitFlags = OBJ_EMIT_PARTICLE_1; } else { - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; } if (get_number_of_active_players() < 2) { - func_800AFC3C(obj, updateRate); + obj_spawn_particle(obj, updateRate); } } @@ -5672,43 +5797,56 @@ void obj_init_unknown94(UNUSED Object *obj, UNUSED LevelObjectEntry_Unknown94 *e void obj_loop_unknown94(UNUSED Object *obj, s32 UNUSED updateRate) { } +/** + * Particle Emitter init func. + * Does nothing. + */ void obj_init_rangetrigger(UNUSED Object *obj, UNUSED LevelObjectEntry_RangeTrigger *entry) { } -/* Official name: rangetriggerControl */ +/** + * Particle Emitter loop func. + * Emits particles set by the spawn parameters when any races are in range. + * Official name: rangetriggerControl + */ void obj_loop_rangetrigger(Object *obj, s32 updateRate) { UNUSED s32 pad; - LevelObjectEntry_RangeTrigger *level_entry; + LevelObjectEntry_RangeTrigger *entry; Object *objs[8]; - level_entry = &obj->segment.level_entry->rangeTrigger; - if (func_80016DE8(obj->segment.trans.x_position, 0, obj->segment.trans.z_position, level_entry->unk8, 1, objs) > - 0) { - obj->unk74 = level_entry->unkA; + entry = &obj->segment.level_entry->rangeTrigger; + if (obj_dist_racer(obj->segment.trans.x_position, 0, obj->segment.trans.z_position, entry->radius, 1, objs) > 0) { + obj->particleEmitFlags = entry->particleFlags; } else { - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; } - func_800AFC3C(obj, updateRate); + obj_spawn_particle(obj, updateRate); } +/** + * Overworld Frog init func. + * Sets the home position to where it is currently. + * Checks if this frog is supposed to be drumstick. + * If so, delete if Drumstick is either unlocked, or all trophy races are not yet complete. + */ void obj_init_frog(Object *obj, LevelObjectEntry_Frog *entry) { - Object_Frog *obj64; + Object_Frog *frog; - obj64 = &obj->unk64->frog; - obj64->drumstick = entry->drumstick; - obj64->homeX = obj->segment.trans.x_position; - obj64->homeY = obj->segment.trans.y_position; - obj64->homeZ = obj->segment.trans.z_position; - obj64->homeRadius = entry->homeRadius; - obj64->homeRadiusSquare = obj64->homeRadius * obj64->homeRadius; - obj64->action = FROG_IDLE; - obj64->hopStartX = obj->segment.trans.x_position; - obj64->hopStartZ = obj->segment.trans.z_position; - obj64->squishCooldown = 0; - obj64->scaleY = 1.0f; + frog = &obj->unk64->frog; + frog->drumstick = entry->drumstick; + frog->homeX = obj->segment.trans.x_position; + frog->homeY = obj->segment.trans.y_position; + frog->homeZ = obj->segment.trans.z_position; + frog->homeRadius = entry->homeRadius; + frog->homeRadiusSquare = frog->homeRadius * frog->homeRadius; + frog->action = FROG_IDLE; + frog->hopStartX = obj->segment.trans.x_position; + frog->hopStartZ = obj->segment.trans.z_position; + frog->squishCooldown = 0; + frog->scaleY = 1.0f; - if (obj64->drumstick) { - obj->segment.object.modelIndex = TRUE; + if (frog->drumstick) { + obj->segment.object.modelIndex = 1; /** * Don't spawn the chicken frog if drumstick is already unlocked, or * if the player hasn't completed the trophy races yet. @@ -5717,7 +5855,7 @@ void obj_init_frog(Object *obj, LevelObjectEntry_Frog *entry) { free_object(obj); } } else { - obj->segment.object.modelIndex = FALSE; + obj->segment.object.modelIndex = 0; } } @@ -5755,8 +5893,8 @@ void obj_loop_frog(Object *obj, s32 updateRate) { if (frog->squishCooldown > 0) { frog->squishCooldown -= updateRate; } - if (func_80016DE8(obj->segment.trans.x_position, obj->segment.trans.y_position, - obj->segment.trans.z_position, 96.0f, 1, &racerObj) > 0) { + if (obj_dist_racer(obj->segment.trans.x_position, obj->segment.trans.y_position, + obj->segment.trans.z_position, 96.0f, 1, &racerObj) > 0) { diffX = obj->segment.trans.x_position - racerObj->segment.trans.x_position; diffY = obj->segment.trans.y_position - racerObj->segment.trans.y_position; diffZ = obj->segment.trans.z_position - racerObj->segment.trans.z_position; @@ -5770,7 +5908,7 @@ void obj_loop_frog(Object *obj, s32 updateRate) { free_object(obj); break; } else { - frog->action = 2; + frog->action = FROG_SQUISH; play_sound_at_position(SOUND_SPLAT, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); } @@ -5847,8 +5985,8 @@ void obj_loop_frog(Object *obj, s32 updateRate) { move_object(obj, 0.0f, sp6C, 0.0f); } if (frog->squishCooldown <= 0 && (frog->hopFrame < 6 || frog->hopFrame >= 27)) { - if (func_80016DE8(obj->segment.trans.x_position, obj->segment.trans.y_position, - obj->segment.trans.z_position, 40.0f, 0, &racerObj)) { + if (obj_dist_racer(obj->segment.trans.x_position, obj->segment.trans.y_position, + obj->segment.trans.z_position, 40.0f, 0, &racerObj)) { if (frog->drumstick) { play_sound_at_position(SOUND_VOICE_DRUMSTICK_POSITIVE2, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); diff --git a/src/object_functions.h b/src/object_functions.h index a909c3a1..41fa3b11 100644 --- a/src/object_functions.h +++ b/src/object_functions.h @@ -13,6 +13,27 @@ #define TIME_SECONDS(sec) sec * TIME_JIFFIES_PER_SECOND #define U8_ANGLE_TO_U16(x) (x << 6 << 4) +enum BananaBehaviour { + BANANA_COLLECTED = -1, + BANANA_IDLE, + BANANA_DROPPED +}; + +enum WeaponBehaviour { + WEAPON_DROPPED, + WEAPON_ARMED, + WEAPON_TRIGGERED, + WEAPON_DESTROY, + WEAPON_STATUS_4, + WEAPON_STATUS_5 +}; + +enum DoorStatus { + DOOR_CLOSING = -1, + DOOR_CLOSED, + DOOR_OPENING +}; + enum BossRaceWarps { WARP_STANDARD = -1, WARP_BOSS_FIRST, @@ -28,7 +49,7 @@ enum TajBehaviours { TAJ_MODE_TRANSFORM_BEGIN, TAJ_MODE_TRANSFORM_END, TAJ_MODE_END_DIALOGUE, - TAJ_MODE_END_DIALOGUE_UNUSED, + TAJ_MODE_END_DIALOGUE_CHALLENGE, TAJ_MODE_TELEPORT_TO_PLAYER_BEGIN = 10, TAJ_MODE_TELEPORT_TO_PLAYER_END, TAJ_MODE_SET_CHALLENGE = 15, @@ -261,8 +282,8 @@ void obj_loop_eggcreator(Object *obj, s32 updateRate); void obj_init_lighthouse_rocketsignpost(Object *obj, LevelObjectEntry_Lighthouse_RocketSignpost *entry); void obj_loop_rocketsignpost(Object *obj, s32 updateRate); void obj_init_airzippers_waterzippers(Object *obj, LevelObjectEntry_AirZippers_WaterZippers *entry); -void obj_init_unknown58(Object *obj, LevelObjectEntry_Unknown58 *entry); -void obj_loop_unknown58(Object *obj, s32 updateRate); +void obj_init_timetrialghost(Object *obj, LevelObjectEntry_TimeTrial_Ghost *entry); +void obj_loop_timetrialghost(Object *obj, s32 updateRate); void obj_init_characterflag(Object *obj, LevelObjectEntry_CharacterFlag *entry); void obj_loop_characterflag(Object *obj, s32 updateRate); void obj_init_stopwatchman(Object *obj, LevelObjectEntry_StopWatchMan *entry); @@ -391,7 +412,7 @@ void obj_loop_door(Object *doorObj, s32 updateRate); void obj_loop_fish(Object *fishObj, s32 updateRate); void obj_loop_weaponballoon(Object *weaponBalloonObj, s32 updateRate); void obj_loop_char_select(Object *charSelectObj, s32 updateRate); -void func_8003F2E8(Object *weaponObj, s32 updateRate); +void weapon_trap(Object *weaponObj, s32 updateRate); void obj_init_butterfly(Object *butterflyObj, LevelObjectEntry_Butterfly *butterflyEntry, s32 param); void obj_init_animation(Object *obj, LevelObjectEntry_Animation *entry, s32 arg2); void obj_init_lensflareswitch(Object *obj, LevelObjectEntry_LensFlareSwitch *entry, UNUSED s32 arg2); @@ -413,7 +434,7 @@ void obj_init_door(Object *obj, LevelObjectEntry_Door *entry); void obj_init_audio(Object *obj, LevelObjectEntry_Audio *entry); void obj_init_bombexplosion(Object *obj, LevelObjectEntry_BombExplosion *entry); void obj_init_scenery(Object *obj, LevelObjectEntry_Scenery *entry); -void handle_rocket_projectile(Object *obj, s32 updateRate); +void weapon_projectile(Object *obj, s32 updateRate); //Non Matching void calc_env_mapping_for_object(ObjectModel *, s16, s16, s16); @@ -422,7 +443,7 @@ void obj_init_midifade(Object *obj, LevelObjectEntry_MidiFade *entry); void obj_loop_texscroll(Object *obj, s32 updateRate); void obj_loop_butterfly(Object *obj, s32 updateRate); void obj_loop_animator(Object *obj, s32 updateRate); -s32 func_8001C524(f32 diffX, f32 diffY, f32 diffZ, s32 someFlag); +s32 ainode_find_nearest(f32 diffX, f32 diffY, f32 diffZ, s32 useElevation); s32 func_8001CC48(s32, s32, s32); f32 func_8001C6C4(Object_64 *, Object *, f32, f32, s32); void func_8000CBF0(Object*, s32); diff --git a/src/object_models.c b/src/object_models.c index d0e8a3b9..35c93243 100644 --- a/src/object_models.c +++ b/src/object_models.c @@ -66,6 +66,7 @@ void allocate_object_model_pools(void) { D_8011D644 = (s32) allocate_from_main_pool_safe(0xC00, COLOUR_TAG_GREEN); D_8011D640 = 0; +#ifdef ANTI_TAMPER // Antipiracy measure checksum = 0; for (i = 0; i < gTrackRenderFuncLength; i++) { @@ -74,6 +75,7 @@ void allocate_object_model_pools(void) { if (checksum != gTractionTableChecksum) { antipiracy_modify_surface_traction_table(); } +#endif } /** diff --git a/src/objects.c b/src/objects.c index 095bd472..217a917c 100644 --- a/src/objects.c +++ b/src/objects.c @@ -36,11 +36,13 @@ #define OBJECT_SPAWN_HEAP_SIZE 0x800 #define OBJECT_SLOT_COUNT 512 #define ASSET_OBJECT_HEADER_TABLE_LENGTH 304 // This isn't important, but it's the number of object headers +#define AINODE_COUNT 128 +#define CAMCONTROL_COUNT 20 /************ .data ************/ -FadeTransition D_800DC6F0 = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_OUT, FADE_COLOR_BLACK, 30, 15); -FadeTransition D_800DC6F8 = FADE_TRANSITION(FADE_CIRCLE, FADE_FLAG_NONE, FADE_COLOR_BLACK, 30, 15); +FadeTransition gTajChallengeTransition = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_OUT, FADE_COLOR_BLACK, 30, 15); +FadeTransition gBalloonCutsceneTransition = FADE_TRANSITION(FADE_CIRCLE, FADE_FLAG_NONE, FADE_COLOR_BLACK, 30, 15); s32 D_800DC700 = 0; s32 D_800DC704 = 0; // Currently unknown, might be a different type. @@ -48,13 +50,13 @@ s16 D_800DC708 = 0; s32 D_800DC70C = 0; // Currently unknown, might be a different type. s16 D_800DC710 = 1; s32 D_800DC714 = 0; // Currently unknown, might be a different type. -Object *gGhostObj = NULL; +Object *gGhostObjStaff = NULL; s8 D_800DC71C = 0; s32 gObjectTexAnim = FALSE; -s16 D_800DC724 = 0x2A30; -s16 D_800DC728 = -1; -s16 D_800DC72C = 0; -u8 gHasGhostToSave = 0; +s16 gTimeTrialTime = 0x2A30; +s16 gTimeTrialVehicle = -1; +s16 gTimeTrialCharacter = 0; +u8 gHasGhostToSave = FALSE; u8 gTimeTrialStaffGhost = FALSE; u8 gBeatStaffGhost = FALSE; s8 D_800DC73C = 0; @@ -165,8 +167,8 @@ u32 gMagnetColours[3] = { COLOUR_RGBA32(16, 64, 255, 0), // Level 2 COLOUR_RGBA32(16, 255, 64, 0), // Level 3 }; -FadeTransition D_800DC858 = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_NONE, FADE_COLOR_BLACK, 40, 0xFFFF); -FadeTransition D_800DC860 = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_OUT, FADE_COLOR_BLACK, 40, 0); +FadeTransition gRaceEndFade = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_NONE, FADE_COLOR_BLACK, 40, -1); +FadeTransition gRaceEndTransition = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_OUT, FADE_COLOR_BLACK, 40, 0); /*******************************/ @@ -201,8 +203,8 @@ s8 D_8011AD26; f32 D_8011AD28; s32 D_8011AD2C; f32 gCurrentLightIntensity; -Object *D_8011AD34; -s32 D_8011AD38; // D_8011AD38 is ultimately set by func_80074B34, and is almost definitely SIDeviceStatus +Object *gGhostObjPlayer; +s32 gTimeTrialContPak; // gTimeTrialContPak is ultimately set by func_80074B34, and is almost definitely SIDeviceStatus s8 D_8011AD3C; s8 D_8011AD3D; s8 D_8011AD3E; @@ -213,10 +215,10 @@ s16 gTransformPosX; s16 gTransformPosY; s16 gTransformPosZ; s16 gTransformAngleY; -s16 D_8011AD4E; -s8 D_8011AD50; +s16 gRaceEndTimer; +s8 gRaceEndStage; s8 gNumRacersSaved; -s8 D_8011AD52; +UNUSED s8 unused_D_8011AD52; s8 D_8011AD53; s32 D_8011AD54; Object *(*gSpawnObjectHeap)[sizeof(Object)]; @@ -231,7 +233,7 @@ Gfx *D_8011AD78[10]; s32 gAssetsMiscTableLength; s16 D_8011ADA4; f32 gObjectUpdateRateF; -s32 D_8011ADAC; +s32 gPathUpdateOff; s32 gEventCountdown; s32 D_8011ADB4; s32 gEventStartTimer; @@ -241,9 +243,9 @@ s8 gFirstTimeFinish; s8 D_8011ADC5; u32 gBalloonCutsceneTimer; s8 (*D_8011ADCC)[8]; -f32 D_8011ADD0; +f32 gObjectOffsetY; s8 D_8011ADD4; -s8 D_8011ADD5; +s8 gOverrideDoors; Object *D_8011ADD8[10]; // Array of OverRidePos objects s8 D_8011AE00; // Number of OverRidePos objects in D_8011ADD8 s8 D_8011AE01; // A boolean? I've seen it either as 0 or 1 @@ -267,8 +269,8 @@ s16 gCutsceneID; s16 D_8011AE7C; s8 D_8011AE7E; s16 gTTGhostTimeToBeat; -s16 D_8011AE82; // Current Vehicle being used in track? -s16 gMapDefaultVehicle; // Vehicle enum +s16 gPrevTimeTrialVehicle; // Current Vehicle being used in track? +s16 gMapDefaultVehicle; // Vehicle enum s32 D_8011AE88; Gfx *gObjectCurrDisplayList; MatrixS *gObjectCurrMatrix; @@ -286,8 +288,8 @@ CheckpointNode *gTrackCheckpoints; // Array of structs, unknown number of member s32 gNumberOfCheckpoints; s32 D_8011AED4; s16 gTajChallengeType; -Object *(*gCameraObjList)[20]; // Camera objects with a maximum of 20 -s32 gCameraObjCount; // The number of camera objects in the above list +Object *(*gCameraObjList)[CAMCONTROL_COUNT]; // Camera objects with a maximum of 20 +s32 gCameraObjCount; // The number of camera objects in the above list Object *(*gRacers)[10]; // Similar to gRacers, but sorts the pointer by the players' current position in the race. Object **gRacersByPosition; @@ -297,15 +299,15 @@ s32 gNumRacers; u8 gTimeTrialEnabled; u8 gIsTimeTrial; s8 gIsTajChallenge; -s8 D_8011AEF7; -s8 D_8011AEF8; -s32 D_8011AEFC; +s8 gTajRaceInit; +s8 gChallengePrevMusic; +s32 gChallengePrevInstruments; s8 D_8011AF00; -Object *(*D_8011AF04)[128]; -s32 D_8011AF08[2]; -s32 D_8011AF10[2]; -f32 D_8011AF18[4]; -s32 D_8011AF28; +Object *(*gAINodes)[AINODE_COUNT]; +s32 gAINodeTail[2]; +s32 gInitAINodes; +s32 D_8011AF14; +f32 gElevationHeights[5]; s32 D_8011AF2C; ShadeProperties *gWorldShading; // Effectively unused. s32 D_8011AF34; @@ -330,7 +332,7 @@ u8 D_8011B078[3]; u8 D_8011B07B[1]; s32 D_8011B080[7]; -extern s16 D_8011D5AC; +extern s16 gGhostMapID; /******************************/ @@ -410,9 +412,9 @@ void func_8000BADC(s32 updateRate) { updateRateF *= 1.2f; } racer = &(*gRacers)[i]->unk64->racer; - asset20Part = &asset20[racer->unk2]; + asset20Part = &asset20[racer->racerIndex]; if (racer->shieldTimer != 0) { - D_8011B010[racer->unk2] += updateRate; + D_8011B010[racer->racerIndex] += updateRate; } asset20Part->unk72 += updateRate; if (racer->boostTimer != 0) { @@ -463,9 +465,9 @@ void func_8000BADC(s32 updateRate) { } } if ((asset20Part->unk70 > 0) || (asset20Part->unk74 > 0.0f)) { - func_8000B750((*gRacers)[i], racer->unk2, racer->vehicleIDPrev, racer->boostType, 0); + func_8000B750((*gRacers)[i], racer->racerIndex, racer->vehicleIDPrev, racer->boostType, 0); } - temp = racer->unk2 << 2; + temp = racer->racerIndex << 2; D_8011B078[temp + 1] += updateRate; D_8011B078[temp + 2] += updateRate; if (racer->magnetTimer != 0) { @@ -507,16 +509,16 @@ void allocate_object_pools(void) { set_world_shading(0.67f, 0.33f, 0, -0x2000, 0); gObjectMemoryPool = (Object *) new_sub_memory_pool(OBJECT_POOL_SIZE, OBJECT_SLOT_COUNT); gParticlePtrList = allocate_from_main_pool_safe(sizeof(uintptr_t) * 200, COLOUR_TAG_BLUE); - D_8011AE6C = allocate_from_main_pool_safe(0x50, COLOUR_TAG_BLUE); - D_8011AE74 = allocate_from_main_pool_safe(0x200, COLOUR_TAG_BLUE); + D_8011AE6C = allocate_from_main_pool_safe(sizeof(uintptr_t) * 20, COLOUR_TAG_BLUE); + D_8011AE74 = allocate_from_main_pool_safe(sizeof(uintptr_t) * 128, COLOUR_TAG_BLUE); gTrackCheckpoints = allocate_from_main_pool_safe(sizeof(CheckpointNode) * MAX_CHECKPOINTS, COLOUR_TAG_BLUE); - gCameraObjList = allocate_from_main_pool_safe(sizeof(uintptr_t *) * 20, COLOUR_TAG_BLUE); + gCameraObjList = allocate_from_main_pool_safe(sizeof(uintptr_t *) * CAMCONTROL_COUNT, COLOUR_TAG_BLUE); gRacers = allocate_from_main_pool_safe(sizeof(uintptr_t) * 10, COLOUR_TAG_BLUE); gRacersByPort = allocate_from_main_pool_safe(sizeof(uintptr_t) * 10, COLOUR_TAG_BLUE); gRacersByPosition = allocate_from_main_pool_safe(sizeof(uintptr_t) * 10, COLOUR_TAG_BLUE); - D_8011AF04 = allocate_from_main_pool_safe(0x200, COLOUR_TAG_BLUE); + gAINodes = allocate_from_main_pool_safe(sizeof(uintptr_t) * AINODE_COUNT, COLOUR_TAG_BLUE); D_8011ADCC = allocate_from_main_pool_safe(8, COLOUR_TAG_BLUE); - D_8011AFF4 = allocate_from_main_pool_safe(0x400, COLOUR_TAG_BLUE); + D_8011AFF4 = allocate_from_main_pool_safe(sizeof(unk800179D0) * 16, COLOUR_TAG_BLUE); gAssetsLvlObjTranslationTable = (s16 *) load_asset_section_from_rom(ASSET_LEVEL_OBJECT_TRANSLATION_TABLE); gAssetsLvlObjTranslationTableLength = (get_size_of_asset_section(ASSET_LEVEL_OBJECT_TRANSLATION_TABLE) >> 1) - 1; while (gAssetsLvlObjTranslationTable[gAssetsLvlObjTranslationTableLength] == 0) { @@ -605,8 +607,8 @@ void clear_object_pointers(void) { D_8011AD22[0] = 0; D_8011AD22[1] = 0; - for (i = 0; i < 128; i++) { - (*D_8011AF04)[i] = 0; + for (i = 0; i < AINODE_COUNT; i++) { + (*gAINodes)[i] = NULL; } for (i = 0; i < 8; i++) { (*D_8011ADCC)[i] = 0; @@ -615,8 +617,8 @@ void clear_object_pointers(void) { D_8011AFF4[i].unk0 = 0; } - D_8011AF08[0] = 0xFF; - D_8011AF08[1] = 0xFF; + gAINodeTail[0] = 0xFF; + gAINodeTail[1] = 0xFF; gObjectCount = 0; gObjectListStart = 0; gParticleCount = 0; @@ -627,12 +629,12 @@ void clear_object_pointers(void) { D_8011AE7C = 0; gTransformTimer = 0; gIsTajChallenge = FALSE; - D_8011AEF7 = 0; + gTajRaceInit = 0; D_8011AF60[0] = 0; D_8011AE00 = 0; D_8011AE01 = 1; D_8011AD53 = 0; - D_8011ADD5 = FALSE; + gOverrideDoors = FALSE; } /** @@ -641,7 +643,7 @@ void clear_object_pointers(void) { */ void free_all_objects(void) { s32 i, len; - free_tt_ghost_data(); + timetrial_free_staff_ghost(); D_800DC748 = 0; if (D_800DC71C) { rumble_init(TRUE); @@ -783,13 +785,13 @@ void func_8000C8F8(s32 arg0, s32 arg1) { D_8011AE98[arg1] = (u8 *) (D_8011AEB0[arg1] + 4); D_8011AE70 = 0; D_8011ADC0 = 1; - if (D_8011ADAC == 0) { + if (gPathUpdateOff == FALSE) { gParticlePtrList_flush(); func_80017E98(); - func_8001BC54(); + spectate_update(); func_8001E93C(); } - D_8011ADAC = 1; + gPathUpdateOff = TRUE; } } @@ -829,6 +831,7 @@ s32 func_8000CC20(Object *obj) { } #ifdef NON_EQUIVALENT +// track_init_racers void func_8000CC7C(Vehicle vehicle, u32 arg1, s32 arg2) { s32 numPlayers; // sp144 enum GameMode gameMode; @@ -886,7 +889,7 @@ void func_8000CC7C(Vehicle vehicle, u32 arg1, s32 arg2) { gameMode = get_game_mode(); settings = get_settings(); miscAsset16 = (s8 *) get_misc_asset(3); - D_8011AE82 = D_8011ADC5; + gPrevTimeTrialVehicle = D_8011ADC5; tajFlags = settings->courseFlagsPtr[settings->courseId]; if (!(tajFlags & 1)) { // Check if the player has not visited the course yet. settings->courseFlagsPtr[settings->courseId] = tajFlags | 1; @@ -904,12 +907,12 @@ void func_8000CC7C(Vehicle vehicle, u32 arg1, s32 arg2) { curObj = gObjPtrList[i2]; if (!(curObj->segment.trans.flags & OBJ_FLAGS_DEACTIVATED)) { if (curObj->behaviorId == BHV_SETUP_POINT) { - if (arg1 == (u32) curObj->properties.setupPoint.unk4) { - if (curObj->properties.setupPoint.unk0 < 8) { - spF4[curObj->properties.setupPoint.unk0] = curObj->segment.trans.x_position; - spD4[curObj->properties.setupPoint.unk0] = curObj->segment.trans.y_position; - spB4[curObj->properties.setupPoint.unk0] = curObj->segment.trans.z_position; - sp94[curObj->properties.setupPoint.unk0] = curObj->segment.trans.y_rotation; + if (arg1 == (u32) curObj->properties.setupPoint.entranceID) { + if (curObj->properties.setupPoint.racerIndex < 8) { + spF4[curObj->properties.setupPoint.racerIndex] = curObj->segment.trans.x_position; + spD4[curObj->properties.setupPoint.racerIndex] = curObj->segment.trans.y_position; + spB4[curObj->properties.setupPoint.racerIndex] = curObj->segment.trans.z_position; + sp94[curObj->properties.setupPoint.racerIndex] = curObj->segment.trans.y_rotation; } tempVehicle = curObj->segment.level_entry->setupPoint.vehicle; if (tempVehicle != -1) { @@ -920,7 +923,7 @@ void func_8000CC7C(Vehicle vehicle, u32 arg1, s32 arg2) { } } D_8011ADC5 = vehicle; - D_8011AE82 = D_8011ADC5; + gPrevTimeTrialVehicle = D_8011ADC5; numPlayers = arg2 + 1; gNumRacers = 8; D_800DC740 = 0; @@ -1104,7 +1107,7 @@ void func_8000CC7C(Vehicle vehicle, u32 arg1, s32 arg2) { if (tempVehicle < VEHICLE_CAR || tempVehicle > VEHICLE_PLANE) { curRacer->unk1CB = 0; } - curRacer->unk2 = var_s4; + curRacer->racerIndex = var_s4; curRacer->characterId = settings->racers[var_s4].character; if (D_8011AD3C == 2) { curRacer->characterId = D_800DC840[i6]; @@ -1162,18 +1165,18 @@ void func_8000CC7C(Vehicle vehicle, u32 arg1, s32 arg2) { } } } - gGhostObj = 0; - free_tt_ghost_data(); - D_8011AD38 = -1; + gGhostObjStaff = 0; + timetrial_free_staff_ghost(); + gTimeTrialContPak = -1; if ((gIsTimeTrial) && (numPlayers == 1)) { - func_80059944(); - D_8011AD38 = func_8001B668(0); + timetrial_reset_player_ghost(); + gTimeTrialContPak = timetrial_init_player_ghost(0); gHasGhostToSave = 0; - if (D_800DC728 >= 5) { - D_800DC728 = 0; + if (gTimeTrialVehicle >= 5) { + gTimeTrialVehicle = 0; } - if (func_8001B288() != 0) { - objectId = D_800DC7A8[(D_800DC728 * 10) + D_800DC72C]; + if (timetrial_valid_player_ghost() != 0) { + objectId = D_800DC7A8[(gTimeTrialVehicle * 10) + gTimeTrialCharacter]; entry->common.size = ((objectId & 0x100) >> 1) | 0x10; entry->common.objectID = objectId; entry->common.x = spF4[0]; @@ -1182,13 +1185,13 @@ void func_8000CC7C(Vehicle vehicle, u32 arg1, s32 arg2) { entry->unkC = sp94[0]; newRacerObj = spawn_object((LevelObjectEntryCommon *) entry, 1); newRacerObj->segment.level_entry = NULL; - newRacerObj->behaviorId = BHV_UNK_3A; + newRacerObj->behaviorId = BHV_TIMETRIAL_GHOST; newRacerObj->shadow->scale = 0.01f; newRacerObj->interactObj->flags = 0; - D_8011AD34 = newRacerObj; + gGhostObjPlayer = newRacerObj; newRacerObj->unk64->racer.transparency = 0x60; } - if (func_8001B4FC(get_current_map_id()) != 0) { + if (timetrial_init_staff_ghost(get_current_map_id()) != 0) { objectId = D_800DC7B8[gMapDefaultVehicle * 10]; entry->common.size = ((objectId & 0x100) >> 1) | 0x10; entry->common.objectID = objectId; @@ -1198,10 +1201,10 @@ void func_8000CC7C(Vehicle vehicle, u32 arg1, s32 arg2) { entry->unkC = sp94[0]; newRacerObj = spawn_object((LevelObjectEntryCommon *) entry, 1); newRacerObj->segment.level_entry = NULL; - newRacerObj->behaviorId = BHV_UNK_3A; + newRacerObj->behaviorId = BHV_TIMETRIAL_GHOST; newRacerObj->shadow->scale = 0.01f; newRacerObj->interactObj->flags = 0; - gGhostObj = newRacerObj; + gGhostObjStaff = newRacerObj; newRacerObj->unk64->racer.transparency = 0x60; } } @@ -1259,7 +1262,7 @@ void func_8000CC7C(Vehicle vehicle, u32 arg1, s32 arg2) { } } } - D_8011AD4E = 0; + gRaceEndTimer = 0; D_8011ADB4 = 0; set_next_taj_challenge_menu(0); if (settings->worldId == WORLD_CENTRAL_AREA) { @@ -1308,8 +1311,8 @@ GLOBAL_ASM("asm/non_matchings/objects/func_8000CC7C.s") * Categorises multiple different controller pak messages into one for fewer cases. */ s32 get_contpak_error(void) { - // D_8011AD38 is likely an SIDeviceStatus value, but not 100% sure yet. - switch (D_8011AD38) { + // gTimeTrialContPak is likely an SIDeviceStatus value, but not 100% sure yet. + switch (gTimeTrialContPak) { case CONTROLLER_PAK_NOT_FOUND: return CONTPAK_ERROR_MISSING; case CONTROLLER_PAK_RUMBLE_PAK_FOUND: @@ -1323,7 +1326,7 @@ s32 get_contpak_error(void) { case CONTROLLER_PAK_GOOD: case CONTROLLER_PAK_CHANGED: case CONTROLLER_PAK_SWITCH_TO_RUMBLE: - return func_80059E20(); + return timetrial_ghost_full(); default: return CONTPAK_ERROR_NONE; } @@ -1438,7 +1441,7 @@ void transform_player_vehicle(void) { racer = &player->unk64->racer; racer->vehicleID = gOverworldVehicle; racer->vehicleIDPrev = gOverworldVehicle; - racer->unk2 = 0; + racer->racerIndex = 0; racer->characterId = settings->racers[PLAYER_ONE].character; racer->playerIndex = 0; racer->vehicleSound = 0; @@ -1784,8 +1787,8 @@ Object *spawn_object(LevelObjectEntryCommon *entry, s32 arg1) { curObj->unk60 = (Object_60 *) address; address += 0xC; } - if (curObj->segment.header->unk57 > 0) { - address = (u32 *) ((uintptr_t) address + func_8000FAC4(curObj, (Object_6C *) address)); + if (curObj->segment.header->particleCount > 0) { + address = (u32 *) ((uintptr_t) address + obj_init_emitter(curObj, (ParticleEmitter *) address)); } sizeOfobj = (uintptr_t) address - (uintptr_t) curObj; if (curObj->segment.header->numLightSources > 0) { @@ -1843,8 +1846,9 @@ Object *spawn_object(LevelObjectEntryCommon *entry, s32 arg1) { if (newObj->unk60 != NULL) { newObj->unk60 = (Object_60 *) (((uintptr_t) newObj + (uintptr_t) newObj->unk60) - (uintptr_t) gSpawnObjectHeap); } - if (newObj->segment.header->unk57 > 0) { - newObj->unk6C = (Object_6C *) (((uintptr_t) newObj + (uintptr_t) newObj->unk6C) - (uintptr_t) gSpawnObjectHeap); + if (newObj->segment.header->particleCount > 0) { + newObj->particleEmitter = (ParticleEmitter *) (((uintptr_t) newObj + (uintptr_t) newObj->particleEmitter) - + (uintptr_t) gSpawnObjectHeap); } if (newObj->segment.header->numLightSources > 0) { newObj->lightData = @@ -1994,23 +1998,23 @@ s32 func_8000F99C(Object *obj) { return FALSE; } -s32 func_8000FAC4(Object *obj, Object_6C *arg1) { +s32 obj_init_emitter(Object *obj, ParticleEmitter *emitter) { ObjHeaderParticleEntry *particleDataEntry; s32 i; - obj->unk6C = arg1; + obj->particleEmitter = emitter; particleDataEntry = obj->segment.header->objectParticles; - for (i = 0; i < obj->segment.header->unk57; i++) { + for (i = 0; i < obj->segment.header->particleCount; i++) { if ((particleDataEntry[i].upper & 0xFFFF0000) == 0xFFFF0000) { - partInitTrigger((Particle *) &obj->unk6C[i], (particleDataEntry[i].upper >> 8) & 0xFF, + partInitTrigger((Particle *) &obj->particleEmitter[i].unk0, (particleDataEntry[i].upper >> 8) & 0xFF, particleDataEntry[i].upper & 0xFF); } else { - func_800AF29C((Particle *) &obj->unk6C[i], (particleDataEntry[i].upper >> 0x18) & 0xFF, + func_800AF29C((Particle *) &obj->particleEmitter[i].unk0, (particleDataEntry[i].upper >> 0x18) & 0xFF, (particleDataEntry[i].upper >> 0x10) & 0xFF, particleDataEntry[i].upper & 0xFFFF, (particleDataEntry[i].lower >> 0x10) & 0xFFFF, particleDataEntry[i].lower & 0xFFFF); } } - return ((obj->segment.header->unk57 << 5) + 3) & ~3; + return ((obj->segment.header->particleCount * sizeof(ParticleEmitter)) + 3) & ~3; } /** @@ -2153,11 +2157,17 @@ void free_object(Object *object) { gFreeListCount++; } -UNUSED s32 func_80010018(void) { +/** + * Return the length of the object ID table. + */ +UNUSED s32 obj_table_ids(void) { return gAssetsLvlObjTranslationTableLength; } -UNUSED s32 func_80010028(s32 arg0) { +/** + * Return true if the object ID is not higher than the header table length. + */ +UNUSED s32 obj_id_valid(s32 arg0) { return (gAssetsLvlObjTranslationTable[arg0] < gAssetsObjectHeadersTableLength); } @@ -2199,6 +2209,7 @@ GLOBAL_ASM("asm/non_matchings/objects/func_800101AC.s") #ifdef NON_MATCHING // Minor regalloc diffs +// obj_update void func_80010994(s32 updateRate) { s32 i; s32 tempVal; @@ -2312,24 +2323,24 @@ void func_80010994(s32 updateRate) { } } func_8001E6EC(0); - if (D_8011AEF7 != 0) { - func_80022948(); + if (gTajRaceInit != 0) { + mode_init_taj_race(); } - if (D_8011ADAC == 0) { + if (gPathUpdateOff == FALSE) { gParticlePtrList_flush(); func_80017E98(); - func_8001BC54(); + spectate_update(); func_8001E93C(); } if (gNumRacers != 0) { - if (D_8011AD4E == 0) { + if (gRaceEndTimer == 0) { func_80019808(updateRate); } else { - func_8001A8F4(updateRate); + race_transition_adventure(updateRate); } } func_80008438(gRacersByPort, gNumRacers, updateRate); - D_8011ADAC = 1; + gPathUpdateOff = TRUE; gObjectUpdateRateF = (f32) updateRate; D_8011AD24[0] = 0; D_8011AD53 = 0; @@ -2403,10 +2414,10 @@ void func_80011264(ObjectModel *model, Object *obj) { if (model->unk50 > 0) { batch = &model->batches[0]; door = &obj->unk64->door; - current = ((door->unk10 / 10) - 1) << 2; + current = ((door->balloonCount / 10) - 1) << 2; if (model->textures[batch->textureIndex].texture) {} // fakematch if (1) { // fakematch - remaining = ((door->unk10 % 10) << 2); + remaining = ((door->balloonCount % 10) << 2); } for (i = 0; i < model->numberOfBatches; i++, batch++) { if (batch->flags & 0x10000) { @@ -2433,19 +2444,24 @@ UNUSED void do_nothing_func_80011364(UNUSED s32 unused) { } /** - * Return the opposite of D_8011ADAC's value + * Return true if paths are intended to be updated. + * The variable they use here is backwards in terms of use. + * Yes means no, no means yes. */ -UNUSED s32 is_not_D_8011ADAC(void) { - // Ever hear of return !D_8011ADAC? - if (D_8011ADAC) { +UNUSED s32 path_update_check(void) { + // Ever hear of return !gPathUpdateOff? + if (gPathUpdateOff) { return FALSE; } else { return TRUE; } } -void func_80011390(void) { - D_8011ADAC = 0; +/** + * Signal to the game that checkpoints should be updated. + */ +void path_enable(void) { + gPathUpdateOff = FALSE; } /** @@ -3068,7 +3084,7 @@ void object_do_player_tumble(Object *this) { UNUSED s32 unused1; Object_Racer *sp_20; f32 tmp_f2; - f32 sp_1c; + f32 offsetY; f32 tmp_f0; f32 temp; @@ -3078,21 +3094,21 @@ void object_do_player_tumble(Object *this) { this->segment.trans.y_rotation += sp_20->y_rotation_offset; this->segment.trans.x_rotation += sp_20->x_rotation_offset; this->segment.trans.z_rotation += sp_20->z_rotation_offset; - sp_1c = 0.0f; + offsetY = 0.0f; if (sp_20->vehicleIDPrev < VEHICLE_TRICKY) { - sp_1c = coss_f(sp_20->z_rotation_offset); - tmp_f2 = sp_1c; + offsetY = coss_f(sp_20->z_rotation_offset); + tmp_f2 = offsetY; tmp_f0 = coss_f(sp_20->x_rotation_offset - sp_20->unk166) * tmp_f2; tmp_f0 = (tmp_f0 < 0.0f) ? 0.0f : tmp_f0 * tmp_f0; temp = (1.0f - tmp_f0) * 24.0f + sp_20->unkD0; if (0) {} // Fakematch - sp_1c = temp; + offsetY = temp; } - this->segment.trans.y_position = this->segment.trans.y_position + sp_1c; - D_8011ADD0 = sp_1c; + this->segment.trans.y_position = this->segment.trans.y_position + offsetY; + gObjectOffsetY = offsetY; } } @@ -3105,7 +3121,7 @@ void object_undo_player_tumble(Object *obj) { obj->segment.trans.y_rotation -= racer->y_rotation_offset; obj->segment.trans.x_rotation -= racer->x_rotation_offset; obj->segment.trans.z_rotation -= racer->z_rotation_offset; - obj->segment.trans.y_position -= D_8011ADD0; + obj->segment.trans.y_position -= gObjectOffsetY; } } @@ -3147,7 +3163,7 @@ void func_80012F94(Object *obj) { var_t0 = 0; batchNum = 0; } else { - if (obj->behaviorId == BHV_UNK_3A) { // Ghost Object? + if (obj->behaviorId == BHV_TIMETRIAL_GHOST) { // Ghost Object? var_t0 = 1; batchNum = 0; } else { @@ -3338,7 +3354,7 @@ void render_racer_shield(Gfx **dList, MatrixS **mtx, Vertex **vtxList, Object *o struct RacerShieldGfx *shield; s32 shieldType; s32 vehicleID; - s32 var_a2; + s32 racerIndex; f32 scale; f32 shear; @@ -3347,25 +3363,25 @@ void render_racer_shield(Gfx **dList, MatrixS **mtx, Vertex **vtxList, Object *o gObjectCurrDisplayList = *dList; gObjectCurrMatrix = *mtx; gObjectCurrVertexList = *vtxList; - var_a2 = racer->unk2; - if (var_a2 > 10) { - var_a2 = 0; + racerIndex = racer->racerIndex; + if (racerIndex > 10) { + racerIndex = 0; } vehicleID = racer->vehicleID; if (vehicleID >= NUMBER_OF_PLAYER_VEHICLES) { vehicleID = VEHICLE_CAR; } shield = ((struct RacerShieldGfx *) get_misc_asset(ASSET_MISC_SHIELD_DATA)); - vehicleID = (vehicleID * 10) + var_a2; + vehicleID = (vehicleID * 10) + racerIndex; shield = shield + vehicleID; gShieldEffectObject->segment.trans.x_position = shield->x_position; gShieldEffectObject->segment.trans.y_position = shield->y_position; gShieldEffectObject->segment.trans.z_position = shield->z_position; - gShieldEffectObject->segment.trans.y_position += shield->y_offset * sins_f(D_8011B010[var_a2] * 0x200); - shear = (coss_f(D_8011B010[var_a2] * 0x400) * 0.05f) + 0.95f; + gShieldEffectObject->segment.trans.y_position += shield->y_offset * sins_f(D_8011B010[racerIndex] * 0x200); + shear = (coss_f(D_8011B010[racerIndex] * 0x400) * 0.05f) + 0.95f; gShieldEffectObject->segment.trans.scale = shield->scale * shear; shear = shear * shield->turnSpeed; - gShieldEffectObject->segment.trans.y_rotation = D_8011B010[var_a2] * 0x800; + gShieldEffectObject->segment.trans.y_rotation = D_8011B010[racerIndex] * 0x800; gShieldEffectObject->segment.trans.x_rotation = 0x800; gShieldEffectObject->segment.trans.z_rotation = 0; shieldType = racer->shieldType; @@ -3415,7 +3431,7 @@ void render_racer_magnet(Gfx **dList, MatrixS **mtx, Vertex **vtxList, Object *o UNUSED s32 pad; racer = (Object_Racer *) obj->unk64; - var_t0 = racer->unk2 * 4; + var_t0 = racer->racerIndex * 4; if (D_8011B07B[var_t0]) { if (gMagnetEffectObject != NULL) { gObjectCurrDisplayList = *dList; @@ -3427,7 +3443,7 @@ void render_racer_magnet(Gfx **dList, MatrixS **mtx, Vertex **vtxList, Object *o vehicleID = VEHICLE_CAR; } magnet = &magnet[vehicleID * 5]; - var_t0 = racer->unk2; + var_t0 = racer->racerIndex; if (var_t0 > 10) { var_t0 = 0; } @@ -3796,7 +3812,7 @@ void func_80016500(Object *obj, Object_Racer *racer) { sinAngle = sins_f(-angle); racer->lateral_velocity = (obj->segment.x_velocity * cosAngle) + (obj->segment.z_velocity * sinAngle); racer->velocity = (-obj->segment.x_velocity * sinAngle) + (obj->segment.z_velocity * cosAngle); - if (racer->playerIndex != -1) { + if (racer->playerIndex != PLAYER_COMPUTER) { angle = (startVelocity - racer->velocity) * 14.0f; if (angle < 0) { angle = -angle; @@ -3875,9 +3891,9 @@ void func_80016748(Object *obj0, Object *obj1) { zDiff -= obj0->segment.trans.z_position; distance = sqrtf((xDiff * xDiff) + (yDiff * yDiff) + (zDiff * zDiff)); temp += obj1Interact->hitboxRadius; - if ((distance < temp) && (distance > 0.0f)) { - obj0Interact->flags |= 8; - obj1Interact->flags |= 8; + if (distance < temp && distance > 0.0f) { + obj0Interact->flags |= INTERACT_FLAGS_PUSHING; + obj1Interact->flags |= INTERACT_FLAGS_PUSHING; obj0Interact->obj = obj1; obj1Interact->obj = obj0; obj0Interact->distance = 0; @@ -3928,24 +3944,27 @@ void func_80016BC4(Object *obj) { } } -Object *func_80016C68(f32 x, f32 y, f32 z, f32 maxDistCheck, s32 dontCheckYAxis) { - f32 yDiff; - f32 zDiff; - f32 xDiff; +/** + * Find the first butterfly node within range and return a pointer to it. + */ +Object *obj_butterfly_node(f32 x, f32 y, f32 z, f32 maxDistCheck, s32 dontCheckYAxis) { + f32 diffY; + f32 diffZ; + f32 diffX; f32 distance; s32 i; Object *curObj; for (i = 0; i < gObjectCount; i++) { curObj = gObjPtrList[i]; - if (!(curObj->segment.trans.flags & OBJ_FLAGS_DEACTIVATED) && (curObj->behaviorId == BHV_ANIMATED_OBJECT_3)) { - xDiff = curObj->segment.trans.x_position - x; - zDiff = curObj->segment.trans.z_position - z; + if (!(curObj->segment.trans.flags & OBJ_FLAGS_DEACTIVATED) && curObj->behaviorId == BHV_ANIMATED_OBJECT_3) { + diffX = curObj->segment.trans.x_position - x; + diffZ = curObj->segment.trans.z_position - z; if (!dontCheckYAxis) { - yDiff = curObj->segment.trans.y_position - y; - distance = sqrtf((xDiff * xDiff) + (yDiff * yDiff) + (zDiff * zDiff)); + diffY = curObj->segment.trans.y_position - y; + distance = sqrtf((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ)); } else { - distance = sqrtf((xDiff * xDiff) + (zDiff * zDiff)); + distance = sqrtf((diffX * diffX) + (diffZ * diffZ)); } if (distance < maxDistCheck) { return curObj; @@ -3955,7 +3974,12 @@ Object *func_80016C68(f32 x, f32 y, f32 z, f32 maxDistCheck, s32 dontCheckYAxis) return NULL; } -s32 func_80016DE8(f32 x, f32 y, f32 z, f32 radius, s32 is2dCheck, Object **arg5) { +/** + * Compare distance between itself and every racer. + * Any racer within the radius is sorted from nearest to furthest. + * Returns the number of racers within the radius. + */ +s32 obj_dist_racer(f32 x, f32 y, f32 z, f32 radius, s32 is2dCheck, Object **sortObj) { f32 distances[8]; s32 i; s32 j; @@ -3973,7 +3997,7 @@ s32 func_80016DE8(f32 x, f32 y, f32 z, f32 radius, s32 is2dCheck, Object **arg5) for (i = 0; i < gNumRacers; i++) { racerObj = (*gRacers)[i]; racer = &racerObj->unk64->racer; - if ((racer->playerIndex >= 0) && (racer->playerIndex < 4)) { + if (racer->playerIndex >= 0 && racer->playerIndex < 4) { if (is2dCheck) { xDiff = racerObj->segment.trans.x_position - x; zDiff = racerObj->segment.trans.z_position - z; @@ -3986,7 +4010,7 @@ s32 func_80016DE8(f32 x, f32 y, f32 z, f32 radius, s32 is2dCheck, Object **arg5) } if (yDiff < radius) { distances[result] = yDiff; - arg5[result] = (*gRacers)[i]; + sortObj[result] = (*gRacers)[i]; result++; } } @@ -3996,11 +4020,11 @@ s32 func_80016DE8(f32 x, f32 y, f32 z, f32 radius, s32 is2dCheck, Object **arg5) for (j = 0; j < i; j++) { if (distances[j + 1] < distances[j]) { swapf = distances[j]; - swapObj = arg5[j]; + swapObj = sortObj[j]; distances[j] = distances[j + 1]; - arg5[j] = arg5[j + 1]; + sortObj[j] = sortObj[j + 1]; distances[j + 1] = swapf; - arg5[j + 1] = swapObj; + sortObj[j + 1] = swapObj; } } } @@ -4100,7 +4124,7 @@ GLOBAL_ASM("asm/non_matchings/objects/func_80017A18.s") */ void set_taj_challenge_type(s32 vehicleID) { gTajChallengeType = vehicleID; - D_8011ADAC = 0; + gPathUpdateOff = FALSE; } /** @@ -4218,13 +4242,22 @@ s8 set_course_finish_flags(Settings *settings) { return gFirstTimeFinish; } -void func_8001A8D4(s32 arg0) { - D_8011AD4E = 300; - D_8011AD50 = 0; - D_8011AD52 = arg0; +/** + * Sets the countdown ready for the level to fade out. + * Begins the timer that exits the level in 5 seconds. + */ +void race_finish_adventure(UNUSED s32 unusedArg) { + gRaceEndTimer = 300; + gRaceEndStage = 0; + unused_D_8011AD52 = unusedArg; } -void func_8001A8F4(s32 updateRate) { +/** + * Begins counting down, once it reaches 0, start stopping all the race behaviours. + * This function is also where the Taj Balloon cutscene is also handled. + * After that's done, write to save and send the player back to the hub. + */ +void race_transition_adventure(s32 updateRate) { s32 i; Object_Racer *racer; Object *prevPort0Racer; @@ -4234,16 +4267,16 @@ void func_8001A8F4(s32 updateRate) { u32 cutsceneTimerLimit; set_pause_lockout_timer(1); - sp30 = D_8011AD4E; - D_8011AD4E -= updateRate; - if (D_8011AD4E <= 0) { - D_8011AD4E = -1; + sp30 = gRaceEndTimer; + gRaceEndTimer -= updateRate; + if (gRaceEndTimer <= 0) { + gRaceEndTimer = -1; } - if (sp30 > 50 && D_8011AD4E <= 50) { - transition_begin(&D_800DC858); + if (sp30 > 50 && gRaceEndTimer <= 50) { + transition_begin(&gRaceEndFade); } sp30 = 0; - if (D_8011AD50 == 0 && D_8011AD4E == -1) { + if (gRaceEndStage == 0 && gRaceEndTimer == -1) { for (i = 0; i < gNumRacers; i++) { racer = &(*gRacers)[i]->unk64->racer; racer->magnetTargetObj = NULL; @@ -4251,7 +4284,7 @@ void func_8001A8F4(s32 updateRate) { sp30 = i; } if (racer->magnetSoundMask != NULL) { - func_8000488C(racer->magnetSoundMask); + sound_stop(racer->magnetSoundMask); } if (racer->shieldSoundMask != NULL) { func_800096F8(racer->shieldSoundMask); @@ -4279,10 +4312,10 @@ void func_8001A8F4(s32 updateRate) { } } gNumRacersSaved = gNumRacers; - D_8011AD50 = 1; + gRaceEndStage = 1; } - if (D_8011AD50 == 1) { - hud_visibility(0); + if (gRaceEndStage == 1) { + hud_visibility(FALSE); gNumRacersSaved--; if (gNumRacersSaved > 0) { i = 0; @@ -4299,25 +4332,25 @@ void func_8001A8F4(s32 updateRate) { gNumRacers--; } else { - D_8011AD50 = 2; + gRaceEndStage = 2; } } - if (D_8011AD50 == 2) { + if (gRaceEndStage == 2) { prevPort0Racer = (*gRacers)[0]; racer = &prevPort0Racer->unk64->racer; func_800230D0(prevPort0Racer, racer); racer->raceFinished = FALSE; - D_8011AD50 = 3; + gRaceEndStage = 3; func_8001E45C(CUTSCENE_ID_UNK_A); gBalloonCutsceneTimer = 0; func_8001E93C(); } - if (D_8011AD50 == 3) { - transition_begin(&D_800DC860); - D_8011AD50 = 4; + if (gRaceEndStage == 3) { + transition_begin(&gRaceEndTransition); + gRaceEndStage = 4; set_anti_aliasing(TRUE); } - if (D_8011AD50 == 4) { + if (gRaceEndStage == 4) { set_anti_aliasing(TRUE); disable_racer_input(); if (!(get_current_level_race_type() & RACETYPE_CHALLENGE_BATTLE)) { @@ -4340,17 +4373,20 @@ void func_8001A8F4(s32 updateRate) { } if (func_800214C4() != 0 || (i != 0 && check_fadeout_transition() == 0)) { if (i != 0) { - transition_begin(&D_800DC6F8); + transition_begin(&gBalloonCutsceneTransition); } level_transition_begin(2); - D_8011AD50 = 5; + gRaceEndStage = 5; settings->cutsceneFlags |= 0x40000; } } } -s16 func_8001AE44(void) { - return D_8011AD4E; +/** + * Returns the race finish timer. + */ +s16 race_finish_timer(void) { + return gRaceEndTimer; } /** @@ -4360,12 +4396,17 @@ u32 get_balloon_cutscene_timer(void) { return gBalloonCutsceneTimer; } -void func_8001AE64(void) { +/** + * Checks if the fastest lap or the race time is faster than the current record. + * Save those if they are, and if the staff ghost is not enabled, enable it for the next attempt. + * The staff ghost comparison is also called here. + */ +void race_finish_time_trial(void) { s32 bestCourseTime; s32 bestRacerTime; s32 i; s32 courseTime; - s32 temp; + s32 vehicleID; s32 curRacerLapTime; s32 j; Object_Racer *curRacer; @@ -4383,62 +4424,63 @@ void func_8001AE64(void) { bestRacer = &gRacersByPosition[0]->unk64->racer; for (i = 0; i < gNumRacers; i++) { curRacer = &gRacersByPosition[i]->unk64->racer; - if (curRacer->unk2 >= 0) { - if (curRacer->unk2 < get_number_of_active_players()) { - settings->racers[curRacer->unk2].best_times = 0; - temp = curRacer->vehicleIDPrev; - if ((temp >= 0) && (temp < 3)) { + if (curRacer->racerIndex >= 0) { + if (curRacer->racerIndex < get_number_of_active_players()) { + settings->racers[curRacer->racerIndex].best_times = 0; + vehicleID = curRacer->vehicleIDPrev; + if (vehicleID >= VEHICLE_CAR && vehicleID < NUMBER_OF_PLAYER_VEHICLES) { courseTime = 0; for (j = 0; j < levelHeader->laps && j < 5; j++) { - settings->racers[curRacer->unk2].lap_times[j] = curRacer->lap_times[j]; + settings->racers[curRacer->racerIndex].lap_times[j] = curRacer->lap_times[j]; curRacerLapTime = curRacer->lap_times[j]; courseTime += curRacerLapTime; if (curRacerLapTime < bestRacerTime) { settings->unk115[1] = j; - settings->unk115[0] = curRacer->unk2; + settings->unk115[0] = curRacer->racerIndex; bestRacerTime = curRacerLapTime; } } - settings->racers[curRacer->unk2].course_time = courseTime; + settings->racers[curRacer->racerIndex].course_time = courseTime; if (courseTime < bestCourseTime) { bestCourseTime = courseTime; - settings->timeTrialRacer = curRacer->unk2; + settings->timeTrialRacer = curRacer->racerIndex; bestRacer = curRacer; } } } } } - settings->display_times = 0; + settings->display_times = FALSE; if (gIsTimeTrial) { - temp = D_8011AE82; - if ((temp >= 3) || (temp < 0)) { - temp = 0; + vehicleID = gPrevTimeTrialVehicle; + if (vehicleID >= NUMBER_OF_PLAYER_VEHICLES || vehicleID < VEHICLE_CAR) { + vehicleID = VEHICLE_CAR; } - settings->display_times = 1; - if ((settings->unk115[0] == 0)) { - if ((settings->flapTimesPtr[temp][settings->courseId] == 0) || - (bestRacerTime < settings->flapTimesPtr[temp][settings->courseId])) { - settings->flapTimesPtr[temp][settings->courseId] = bestRacerTime; + settings->display_times = TRUE; + if (settings->unk115[0] == 0) { + if ((settings->flapTimesPtr[vehicleID][settings->courseId] == NULL) || + (bestRacerTime < settings->flapTimesPtr[vehicleID][settings->courseId])) { + settings->flapTimesPtr[vehicleID][settings->courseId] = bestRacerTime; settings->racers[settings->unk115[0]].best_times |= 1 << settings->unk115[1]; } } - if ((settings->timeTrialRacer == 0)) { - if ((settings->courseTimesPtr[temp][settings->courseId] == 0) || - (bestCourseTime < settings->courseTimesPtr[temp][settings->courseId])) { - settings->courseTimesPtr[temp][settings->courseId] = bestCourseTime; + if (settings->timeTrialRacer == 0) { + if ((settings->courseTimesPtr[vehicleID][settings->courseId] == NULL) || + (bestCourseTime < settings->courseTimesPtr[vehicleID][settings->courseId])) { + settings->courseTimesPtr[vehicleID][settings->courseId] = bestCourseTime; settings->racers[settings->timeTrialRacer].best_times |= 0x80; } } - if (((!temp) && (!temp)) && (!temp)) {} // Fakematch + if (((!vehicleID) && (!vehicleID)) && (!vehicleID)) {} // Fakematch if (settings->timeTrialRacer == 0) { - if ((bestCourseTime < 10800) && ((temp != D_800DC728) || ((func_800599A8() != get_current_map_id())) || - (bestCourseTime < D_800DC724))) { - D_800DC724 = bestCourseTime; - D_800DC728 = D_8011AE82; - D_800DC72C = settings->racers[0].character; - func_80059984(get_current_map_id()); - gHasGhostToSave = 1; + if (bestCourseTime < 10800 && + (vehicleID != gTimeTrialVehicle || timetrial_map_id() != get_current_map_id() || + bestCourseTime < gTimeTrialTime)) { + gTimeTrialTime = bestCourseTime; + gTimeTrialVehicle = gPrevTimeTrialVehicle; + gTimeTrialCharacter = settings->racers[0].character; + timetrial_swap_player_ghost(get_current_map_id()); + gHasGhostToSave = TRUE; } if (osTvType == TV_TYPE_PAL) { bestCourseTime = (bestCourseTime * 6) / 5; @@ -4456,20 +4498,26 @@ void func_8001AE64(void) { } } -s32 func_8001B288(void) { - if (func_800599A8() != get_current_map_id()) { - return 0; +/** + * Returns true if the player ghost data is valid for playback. + */ +s32 timetrial_valid_player_ghost(void) { + if (timetrial_map_id() != get_current_map_id()) { + return FALSE; } else { - if (D_800DC728 != D_8011AE82) { - return 0; + if (gTimeTrialVehicle != gPrevTimeTrialVehicle) { + return FALSE; } else { - return 1; + return TRUE; } } } -Object *func_8001B2E0(void) { - return D_8011AD34; +/** + * Return the player ghost object. + */ +Object *timetrial_player_ghost(void) { + return gGhostObjPlayer; } /** @@ -4478,7 +4526,7 @@ when TT is on. It looks like it checks some ghost data makes sure you've got a g with the default vehicle, Returns 0 if TT ghost was loaded successfully. */ -s32 func_8001B2F0(s32 mapId) { +s32 timetrial_load_staff_ghost(s32 mapId) { TTGhostTable *ghostTable; TTGhostTable *prevGhostTable; s32 ret; @@ -4510,8 +4558,8 @@ s32 func_8001B2F0(s32 mapId) { /** * Return true if this object is the time trial ghost. */ -s32 is_time_trial_ghost(Object *obj) { - return obj == gGhostObj; +s32 timetrial_staff_ghost_check(Object *obj) { + return obj == gGhostObjStaff; } /** @@ -4523,8 +4571,8 @@ void tt_ghost_beaten(s32 arg0, s16 *playerId) { s32 trackIdCount; s8 *mainTrackIds; - gGhostObj = NULL; - free_tt_ghost_data(); + gGhostObjStaff = NULL; + timetrial_free_staff_ghost(); gTimeTrialStaffGhost = FALSE; mainTrackIds = (s8 *) get_misc_asset(ASSET_MISC_MAIN_TRACKS_IDS); trackIdCount = 0; @@ -4552,26 +4600,31 @@ void tt_ghost_beaten(s32 arg0, s16 *playerId) { play_time_trial_end_message(playerId); } -u8 func_8001B4FC(s32 trackId) { +/** + * Compare if the course record is enough to unlock the staff ghost. + * Also check if the ghost tiself has been beaten. + * Store both results and return if there should be a ghost. + */ +u8 timetrial_init_staff_ghost(s32 trackId) { s32 i; s8 *mainTrackIds; - u16 *temp_v0; + u16 *staffTime; Settings *settings; gBeatStaffGhost = FALSE; gTimeTrialStaffGhost = FALSE; settings = get_settings(); - if (get_map_default_vehicle(trackId) == (Vehicle) D_8011AE82) { + if (get_map_default_vehicle(trackId) == (Vehicle) gPrevTimeTrialVehicle) { mainTrackIds = (s8 *) get_misc_asset(ASSET_MISC_MAIN_TRACKS_IDS); - temp_v0 = (u16 *) get_misc_asset(ASSET_MISC_24); + staffTime = (u16 *) get_misc_asset(ASSET_MISC_GHOST_UNLOCK_TIMES); for (i = 0; mainTrackIds[i] != -1 && trackId != mainTrackIds[i]; i++) {} if (mainTrackIds[i] != -1) { - if (temp_v0[i] >= settings->courseTimesPtr[D_8011AE82][trackId]) { + if (staffTime[i] >= settings->courseTimesPtr[gPrevTimeTrialVehicle][trackId]) { // Check if TT has been beaten? if (!(get_eeprom_settings() & ((1 << 4) << i))) { gBeatStaffGhost = TRUE; } - if (func_8001B2F0(trackId) == 0) { + if (timetrial_load_staff_ghost(trackId) == 0) { gTimeTrialStaffGhost = TRUE; } } @@ -4581,40 +4634,50 @@ u8 func_8001B4FC(s32 trackId) { } /** - * Return the time trial ghost object. + * Return the time trial staff ghost object. */ -Object *get_time_trial_ghost(void) { - return gGhostObj; +Object *timetrial_ghost_staff(void) { + return gGhostObjStaff; } /** * Return true if the tt ghost is unbeaten for this track. */ -s32 unbeaten_staff_time(void) { +s32 timetrial_staff_unbeaten(void) { return gBeatStaffGhost == FALSE; } -s32 func_8001B668(s32 arg0) { - s16 sp2E; - s16 sp2C; - s32 temp_v0; - s32 mapId; +/** + * Calls a function to start loading the player ghost data from the controller pak. + * Returns the controller pak status. 0 means good. + */ +s32 timetrial_init_player_ghost(s32 playerID) { + s16 characterID; + s16 time; + s32 cpakStatus; + s32 ghostMapID; - mapId = func_800599A8(); - if ((get_current_map_id() != mapId) || (D_800DC728 != D_8011AE82)) { - temp_v0 = func_800599B8(arg0, get_current_map_id(), D_8011AE82, &sp2E, &sp2C); - if (temp_v0 == 0) { - D_800DC728 = D_8011AE82; - D_800DC72C = sp2E; - D_800DC724 = sp2C; + ghostMapID = timetrial_map_id(); + if (get_current_map_id() != ghostMapID || gTimeTrialVehicle != gPrevTimeTrialVehicle) { + cpakStatus = + timetrial_load_player_ghost(playerID, get_current_map_id(), gPrevTimeTrialVehicle, &characterID, &time); + if (cpakStatus == CONTROLLER_PAK_GOOD) { + gTimeTrialVehicle = gPrevTimeTrialVehicle; + gTimeTrialCharacter = characterID; + gTimeTrialTime = time; } - return temp_v0; + return cpakStatus; } - return func_800599B8(arg0, get_current_map_id(), D_8011AE82, NULL, NULL); + return timetrial_load_player_ghost(playerID, get_current_map_id(), gPrevTimeTrialVehicle, NULL, NULL); } -SIDeviceStatus func_8001B738(s32 controllerIndex) { - return func_80059B7C(controllerIndex, func_800599A8(), D_800DC728, D_800DC72C, D_800DC724); +/** + * Call a function to write the ghost data to the controller pak. + * Returns the controller pak status. 0 is good. + */ +SIDeviceStatus timetrial_save_player_ghost(s32 controllerIndex) { + return timetrial_write_player_ghost(controllerIndex, timetrial_map_id(), gTimeTrialVehicle, gTimeTrialCharacter, + gTimeTrialTime); } /** @@ -4628,7 +4691,7 @@ u8 has_ghost_to_save(void) { * Resets the variables used for ghost data saving. */ void set_ghost_none(void) { - D_8011D5AC = -1; + gGhostMapID = -1; gHasGhostToSave = FALSE; } @@ -4812,7 +4875,10 @@ UNUSED void debug_render_checkpoint_node(UNUSED s32 checkpointID, UNUSED s32 pat UNUSED MatrixS **mtx, UNUSED Vertex **vtx) { } -void func_8001BC54(void) { +/** + * Loop through every existing spectate camera and sort them by index. + */ +void spectate_update(void) { Object *objPtr; Object *temp; s32 continueLoop; @@ -4823,7 +4889,7 @@ void func_8001BC54(void) { objPtr = gObjPtrList[i]; if (!(objPtr->segment.trans.flags & OBJ_FLAGS_DEACTIVATED)) { if (objPtr->behaviorId == BHV_CAMERA_CONTROL) { - if (gCameraObjCount < 20) { + if (gCameraObjCount < CAMCONTROL_COUNT) { (*gCameraObjList)[gCameraObjCount] = objPtr; gCameraObjCount++; } @@ -4836,7 +4902,7 @@ void func_8001BC54(void) { for (i = 0; i < gCameraObjCount - 1; i++) { objPtr = (*gCameraObjList)[i + 1]; temp = (*gCameraObjList)[i]; - if (temp->properties.common.unk0 > objPtr->properties.common.unk0) { + if (temp->properties.camControl.cameraID > objPtr->properties.camControl.cameraID) { (*gCameraObjList)[i] = (*gCameraObjList)[i + 1]; (*gCameraObjList)[i + 1] = temp; continueLoop = FALSE; @@ -4845,7 +4911,7 @@ void func_8001BC54(void) { } while (!continueLoop); } -Object *get_camera_object(s32 cameraIndex) { +Object *spectate_object(s32 cameraIndex) { if (cameraIndex < 0 || cameraIndex >= gCameraObjCount) { return NULL; } @@ -4856,7 +4922,7 @@ Object *get_camera_object(s32 cameraIndex) { * Take the current camera passed through the function and compare distances between the next and previous camera. * Set the camera to be whichever's closest to the object. */ -Object *find_nearest_spectate_camera(Object *obj, s32 *cameraId) { +Object *spectate_nearest(Object *obj, s32 *cameraId) { Object *nextCamera; Object *prevCamera; Object *currCamera; @@ -4911,162 +4977,180 @@ Object *find_nearest_spectate_camera(Object *obj, s32 *cameraId) { return currCamera; } -void func_8001BF20(void) { +/** + * Take every existing AI node and find each neighbouring node. + * Afterwards, sort them by height so the game can generate elevation thresholds. + */ +void ainode_update(void) { LevelObjectEntry_AiNode *aiNodeEntry; Object *obj; - s16 sp186; + s16 nodeCount; Object *nextAiNodeObj; - f32 xDiff; - f32 zDiff; - f32 yDiff; + f32 diffX; + f32 diffZ; + f32 diffY; s32 i; s32 j; s8 index; // Must be an s8 u8 index2; // Must be an u8 s16 swap; Object_AiNode *aiNodeObj64; - s8 spE4[128]; - s8 sp64[128]; + s8 nodeIDs[AINODE_COUNT]; + s8 elevations[AINODE_COUNT]; - if (D_8011AF10[0] != 0) { - D_8011AF10[0] = 0; - for (i = 0; i < 128; i++) { - (*D_8011AF04)[i] = 0; - } - sp186 = 0; - for (i = 0; i < gObjectCount; i++) { - obj = gObjPtrList[i]; - if (!(obj->segment.trans.flags & OBJ_FLAGS_DEACTIVATED) && (obj->behaviorId == BHV_AINODE)) { - aiNodeEntry = &obj->segment.level_entry->aiNode; - index2 = aiNodeEntry->unk9; - if (!(index2 & 128)) { - (*D_8011AF04)[index2] = obj; - spE4[sp186] = aiNodeEntry->unk9; - sp64[sp186] = aiNodeEntry->unkE & 3; - sp186++; - } + if (gInitAINodes == FALSE) { + return; + } + gInitAINodes = FALSE; + for (i = 0; i < AINODE_COUNT; i++) { + (*gAINodes)[i] = NULL; + } + nodeCount = 0; + // Store each existing node ID in the temporary vars. + for (i = 0; i < gObjectCount; i++) { + obj = gObjPtrList[i]; + if (!(obj->segment.trans.flags & OBJ_FLAGS_DEACTIVATED) && obj->behaviorId == BHV_AINODE) { + aiNodeEntry = &obj->segment.level_entry->aiNode; + index2 = aiNodeEntry->nodeID; + if (!(index2 & AINODE_COUNT)) { + (*gAINodes)[index2] = obj; + nodeIDs[nodeCount] = aiNodeEntry->nodeID; + elevations[nodeCount] = aiNodeEntry->elevation & 3; + nodeCount++; } } - if (sp186 != 0) { - for (i = 0; i < 128; i++) { - obj = (*D_8011AF04)[i]; - if (obj != NULL) { - aiNodeObj64 = (Object_AiNode *) obj->unk64; - aiNodeEntry = &obj->segment.level_entry->aiNode; - for (j = 0; j < 4; j++) { - index2 = aiNodeEntry->unkA[j]; - if (!(index2 & 128)) { - nextAiNodeObj = (*D_8011AF04)[index2]; - aiNodeObj64->nodeObj[j] = nextAiNodeObj; - if (nextAiNodeObj == NULL) { - aiNodeEntry->unkA[j] = -1; - } else { - xDiff = obj->segment.trans.x_position - nextAiNodeObj->segment.trans.x_position; - yDiff = obj->segment.trans.y_position - nextAiNodeObj->segment.trans.y_position; - zDiff = obj->segment.trans.z_position - nextAiNodeObj->segment.trans.z_position; - aiNodeObj64->distToNode[j] = sqrtf((xDiff * xDiff) + (yDiff * yDiff) + (zDiff * zDiff)); - } - } - } - } - } - - do { - j = TRUE; - for (i = 0; i < (sp186 - 1); i++) { - if ((*D_8011AF04)[spE4[i + 1]]->segment.trans.y_position < - (*D_8011AF04)[spE4[i]]->segment.trans.y_position) { - swap = spE4[i]; - spE4[i] = spE4[i + 1]; - spE4[i + 1] = swap; - swap = sp64[i]; - sp64[i] = sp64[i + 1]; - sp64[i + 1] = swap; - j = FALSE; - } - } - } while (!j); // Keep doing this until no more swaps are needed. - - if (1) {} // Fakematch - - for (i = 0; i < 5; i++) { - D_8011AF18[i] = -20000.0f; - } - - index = sp64[0]; - for (i = 0; i < (sp186 - 1);) { - while ((i < (sp186 - 1)) && (index >= sp64[i])) { - i++; - } - if (index < sp64[i]) { - index = sp64[i]; - D_8011AF18[index] = (f32) ((f64) ((*D_8011AF04)[spE4[i]]->segment.trans.y_position + - (*D_8011AF04)[spE4[i - 1]]->segment.trans.y_position) * - 0.5); - } else { - i = sp186; - } - } - D_8011AF18[0] = -10000.0f; - - D_8011AF18[4] = -D_8011AF18[0]; - } } + if (nodeCount == 0) { + return; + } + // Find and set each neighbouring node and distance for each existing node. + for (i = 0; i < AINODE_COUNT; i++) { + obj = (*gAINodes)[i]; + if (obj != NULL) { + aiNodeObj64 = (Object_AiNode *) obj->unk64; + aiNodeEntry = &obj->segment.level_entry->aiNode; + for (j = 0; j < 4; j++) { + index2 = aiNodeEntry->adjacent[j]; + if (!(index2 & AINODE_COUNT)) { + nextAiNodeObj = (*gAINodes)[index2]; + aiNodeObj64->nodeObj[j] = nextAiNodeObj; + if (nextAiNodeObj == NULL) { + aiNodeEntry->adjacent[j] = -1; + } else { + diffX = obj->segment.trans.x_position - nextAiNodeObj->segment.trans.x_position; + diffY = obj->segment.trans.y_position - nextAiNodeObj->segment.trans.y_position; + diffZ = obj->segment.trans.z_position - nextAiNodeObj->segment.trans.z_position; + aiNodeObj64->distToNode[j] = sqrtf((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ)); + } + } + } + } + } + // Sort them by height + do { + j = TRUE; + for (i = 0; i < nodeCount - 1; i++) { + if ((*gAINodes)[nodeIDs[i + 1]]->segment.trans.y_position < + (*gAINodes)[nodeIDs[i]]->segment.trans.y_position) { + swap = nodeIDs[i]; + nodeIDs[i] = nodeIDs[i + 1]; + nodeIDs[i + 1] = swap; + swap = elevations[i]; + elevations[i] = elevations[i + 1]; + elevations[i + 1] = swap; + j = FALSE; + } + } + } while (!j); // Keep doing this until no more swaps are needed. + + if (1) {} // Fakematch + + for (i = 0; i < 5; i++) { + gElevationHeights[i] = -20000.0f; + } + + index = elevations[0]; + for (i = 0; i < nodeCount - 1;) { + while (i < nodeCount - 1 && index >= elevations[i]) { + i++; + } + if (index < elevations[i]) { + index = elevations[i]; + gElevationHeights[index] = ((*gAINodes)[nodeIDs[i]]->segment.trans.y_position + + (*gAINodes)[nodeIDs[i - 1]]->segment.trans.y_position) * + 0.5; + } else { + i = nodeCount; + } + } + gElevationHeights[0] = -10000.0f; + gElevationHeights[4] = -gElevationHeights[0]; } -s16 func_8001C418(f32 yPos) { +/** + * Compare heights against the thresholds. + * Elevation level is set based on position. + */ +s16 obj_elevation(f32 yPos) { s16 i = 0; - s16 out = 0; + s16 elevation = 0; for (; i < 4; i++) { - if ((D_8011AF18[i] != -20000.0f) && (D_8011AF18[i] < yPos)) { - out = i; + if (gElevationHeights[i] != -20000.0f && gElevationHeights[i] < yPos) { + elevation = i; } } - return out; + return elevation; } -s32 func_8001C48C(Object *obj) { +/** + * Loop through the AI Node list and add this new object to the list if it does not already exist. + */ +s32 ainode_register(Object *obj) { s32 i; - for (i = 0; i < 128; i++) { - if ((*D_8011AF04)[i] == 0) { - (*D_8011AF04)[i] = obj; + for (i = 0; i < AINODE_COUNT; i++) { + if ((*gAINodes)[i] == NULL) { + (*gAINodes)[i] = obj; return i; } } return -1; } -s32 func_8001C524(f32 diffX, f32 diffY, f32 diffZ, s32 someFlag) { +/** + * Search through each AI node and find the one closest to the coordinates given. + * Can choose to include or ignore elevation. + */ +s32 ainode_find_nearest(f32 diffX, f32 diffY, f32 diffZ, s32 useElevation) { UNUSED f32 pad[6]; - s32 sp64; + s32 elevation; f32 len; f32 x; f32 z; f32 y; f32 dist; - s32 var_a0; + s32 findDist; s32 numSteps; s32 result; ObjectSegment *segment; - LevelObjectEntry_TTDoor *levelObj; + LevelObjectEntry_AiNode *levelObj; - if (someFlag) { - sp64 = func_8001C418(diffY); + if (useElevation) { + elevation = obj_elevation(diffY); } - dist = (f32) 50000.0; + dist = 50000.0; result = 0xFF; - for (numSteps = 0; numSteps != 128; numSteps++) { - segment = (ObjectSegment *) (*D_8011AF04)[numSteps]; + for (numSteps = 0; numSteps != AINODE_COUNT; numSteps++) { + segment = (ObjectSegment *) (*gAINodes)[numSteps]; if (segment) { - levelObj = &((segment->level_entry)->ttDoor); - var_a0 = 1; - if (someFlag && (sp64 != levelObj->doorID)) { - var_a0 = 0; + levelObj = &((segment->level_entry)->aiNode); + findDist = TRUE; + if (useElevation && elevation != levelObj->elevation) { + findDist = FALSE; } - if ((someFlag == 2) && (levelObj->angleY != 3)) { - var_a0 = 0; + if (useElevation == 2 && levelObj->unk8 != 3) { + findDist = FALSE; } - if (var_a0) { + if (findDist) { x = segment->trans.x_position - diffX; y = segment->trans.y_position - diffY; z = segment->trans.z_position - diffZ; @@ -5084,45 +5168,35 @@ s32 func_8001C524(f32 diffX, f32 diffY, f32 diffZ, s32 someFlag) { GLOBAL_ASM("asm/non_matchings/objects/func_8001C6C4.s") #ifdef NON_MATCHING -typedef struct LevelObjectEntry_Unknown8001CC48 { - LevelObjectEntryCommon common; - u8 pad8[2]; - u8 unkA[4]; -} LevelObjectEntry_Unknown8001CC48; - -typedef struct Object_Unknown8001CC48 { - s8 pad0[0x18]; - s8 unk18[4]; -} Object_Unknown8001CC48; - -s32 func_8001CC48(s32 arg0, s32 arg1, s32 arg2) { - LevelObjectEntry_Unknown8001CC48 *entry; +// ainode_find_next +s32 func_8001CC48(s32 nodeCurrent, s32 arg1, s32 direction) { + LevelObjectEntry_AiNode *entry; Object *someObj; - Object_Unknown8001CC48 *someObj64; + Object_AiNode *someObj64; s32 someCount; s32 i; s32 someIndex; s32 test; - if ((arg0 < -1) || (arg0 >= 128)) { - return 255; + if ((nodeCurrent < -1) || (nodeCurrent >= AINODE_COUNT)) { + return NODE_NONE; } - someObj = (*D_8011AF04)[arg0]; + someObj = (*gAINodes)[nodeCurrent]; if (someObj == NULL) { - return 255; + return NODE_NONE; } - entry = (LevelObjectEntry_Unknown8001CC48 *) someObj->segment.level_entry; - someObj64 = (Object_Unknown8001CC48 *) someObj->unk64; - test = arg2 & 3; + entry = (LevelObjectEntry_AiNode *) someObj->segment.level_entry; + someObj64 = (Object_AiNode *) someObj->unk64; + test = direction & 3; // Swapping these messes up the registers. someCount = 0; - someIndex = (someObj64->unk18[test] + 1) & 3; + someIndex = (someObj64->directions[test] + 1) & 3; for (i = 0; i < 4; i++) { - if (entry->unkA[someIndex] != 255) { - if (entry->unkA[someIndex] != arg1) { - someObj64->unk18[test] = someIndex; + if (entry->adjacent[someIndex] != NODE_NONE) { + if (entry->adjacent[someIndex] != arg1) { + someObj64->directions[test] = someIndex; i = 4; someCount++; } @@ -5130,9 +5204,9 @@ s32 func_8001CC48(s32 arg0, s32 arg1, s32 arg2) { someIndex = (someIndex + 1) & 3; } if (someCount == 0) { - return 255; + return NODE_NONE; } - return entry->unkA[someObj64->unk18[test]]; + return entry->adjacent[someObj64->directions[test]]; } #else GLOBAL_ASM("asm/non_matchings/objects/func_8001CC48.s") @@ -5154,33 +5228,33 @@ s16 func_8001CD28(s32 arg0, s32 arg1, s32 arg2, s32 arg3) { s32 var_ra; Object_AiNode *aiNode; Object *aiNodeObj; - s32 sp154[128]; - s8 spD4[128]; - s8 sp54[128]; + s32 sp154[AINODE_COUNT]; + s8 spD4[AINODE_COUNT]; + s8 sp54[AINODE_COUNT]; // Only matches with do {} while? i = 0; do { sp154[i] = 0; i++; - } while (i < 128); + } while (i < AINODE_COUNT); - aiNodeObj = (*D_8011AF04)[arg0]; + aiNodeObj = (*gAINodes)[arg0]; aiNode = (Object_AiNode *) aiNodeObj->unk64; aiNodeEntry = &aiNodeObj->segment.level_entry->aiNode; var_t1 = 0; var_ra = 0; - result = 0xFF; + result = NODE_NONE; var_s3 = 0; someBool = 1; var_s5 = 0; do { for (i = 0; i < 4; i++) { if (aiNode->nodeObj[i] != 0) { - temp2 = aiNodeEntry->unkA[i]; + temp2 = aiNodeEntry->adjacent[i]; temp = 1; - if (((arg0 == aiNodeEntry->unk9) && (temp2 == arg2)) || - ((arg2 == aiNodeEntry->unk9) && (temp2 == arg0))) { + if (((arg0 == aiNodeEntry->nodeID) && (temp2 == arg2)) || + ((arg2 == aiNodeEntry->nodeID) && (temp2 == arg0))) { temp = 0; if (var_s5 != 0) { temp = 1; @@ -5214,8 +5288,8 @@ s16 func_8001CD28(s32 arg0, s32 arg1, s32 arg2, s32 arg3) { sp36C = var_t1 - 1; - sp54[sp36C] = (someBool) ? aiNodeEntry->unkA[i] : var_s3; - spD4[sp36C] = aiNodeEntry->unkA[i]; + sp54[sp36C] = (someBool) ? aiNodeEntry->adjacent[i] : var_s3; + spD4[sp36C] = aiNodeEntry->adjacent[i]; while ((sp36C > 0) && (sp154[spD4[sp36C - 1]] < sp154[spD4[sp36C]])) { temp = spD4[sp36C]; @@ -5232,14 +5306,14 @@ s16 func_8001CD28(s32 arg0, s32 arg1, s32 arg2, s32 arg3) { if (var_t1 > 0) { var_t1--; - aiNodeObj = (*D_8011AF04)[spD4[var_t1]]; + aiNodeObj = (*gAINodes)[spD4[var_t1]]; aiNodeEntry = &aiNodeObj->segment.level_entry->aiNode; var_s3 = sp54[var_t1]; - var_ra = sp154[aiNodeEntry->unk9]; + var_ra = sp154[aiNodeEntry->nodeID]; aiNode = &aiNodeObj->unk64->ai_node; someBool = 0; if (arg1 & 0x100) { - if ((arg1 & 0x7F) == spD4[var_t1]) { + if ((arg1 & AINODE_COUNT) == spD4[var_t1]) { result = var_s3; } } else if (arg1 == aiNodeEntry->unk8) { @@ -5249,15 +5323,15 @@ s16 func_8001CD28(s32 arg0, s32 arg1, s32 arg2, s32 arg3) { result = var_s3; } } - } while ((result == 0xFF) && (var_t1 > 0)); + } while ((result == NODE_NONE) && (var_t1 > 0)); if (result != 0xFF) { - aiNodeObj = (*D_8011AF04)[arg0]; + aiNodeObj = (*gAINodes)[arg0]; aiNodeEntry = &aiNodeObj->segment.level_entry->aiNode; aiNode = &aiNodeObj->unk64->ai_node; - for (i = 0; (i < 4) && (result != aiNodeEntry->unkA[i]); i++) {} + for (i = 0; (i < 4) && (result != aiNodeEntry->adjacent[i]); i++) {} if (i < 4) { - aiNode->unk18[arg3] = i; + aiNode->directions[arg3] = i; } } return result; @@ -5266,27 +5340,39 @@ s16 func_8001CD28(s32 arg0, s32 arg1, s32 arg2, s32 arg3) { GLOBAL_ASM("asm/non_matchings/objects/func_8001CD28.s") #endif -void func_8001D1AC(void) { - D_8011AF10[0] = 1; +/** + * Signal that AI nodes exist, so the game knows to initialise them. + */ +void ainode_enable(void) { + gInitAINodes = TRUE; } -void func_8001D1BC(s32 arg0) { - if (arg0 != D_8011AF08[0]) { - D_8011AF08[1] = D_8011AF08[0]; - D_8011AF08[0] = arg0; +/** + * If the node ID is new, set the tail ID to it. + */ +void ainode_tail_set(s32 nodeID) { + if (nodeID != gAINodeTail[0]) { + gAINodeTail[1] = gAINodeTail[0]; + gAINodeTail[0] = nodeID; } } -Object *func_8001D1E4(s32 *arg0) { - *arg0 = D_8011AF08[1]; - return D_8011AF04[0][D_8011AF08[1]]; +/** + * Return the last created AI node. + */ +UNUSED Object *ainode_tail(s32 *nodeID) { + *nodeID = gAINodeTail[1]; + return gAINodes[0][gAINodeTail[1]]; } -Object *func_8001D214(s32 arg0) { - if (arg0 >= 0 && arg0 < 0x80) { - return D_8011AF04[0][arg0]; +/** + * Return the AI node assigned to the given ID. + */ +Object *ainode_get(s32 nodeID) { + if (nodeID >= 0 && nodeID < AINODE_COUNT) { + return gAINodes[0][nodeID]; } - return 0; + return NULL; } UNUSED void func_8001D23C(UNUSED s32 arg0, UNUSED s32 arg1, UNUSED s32 arg2) { @@ -5475,20 +5561,23 @@ void func_8001E344(s32 arg0) { } } -void func_8001E36C(s32 arg0, f32 *arg1, f32 *arg2, f32 *arg3) { +/** + * When the sound timer hits the correct value, write the objects position to the arguments. + */ +void obj_bridge_pos(s32 timing, f32 *x, f32 *y, f32 *z) { s32 i; Object *current_obj; - *arg1 = -32000.0f; - *arg2 = -32000.0f; - *arg3 = -32000.0f; + *x = -32000.0f; + *y = -32000.0f; + *z = -32000.0f; for (i = 0; i < gObjectCount; i++) { current_obj = gObjPtrList[i]; if (current_obj != NULL && !(current_obj->segment.trans.flags & OBJ_FLAGS_DEACTIVATED) && - current_obj->behaviorId == BHV_RAMP_SWITCH && current_obj->properties.common.unk0 == arg0) { - *arg1 = current_obj->segment.trans.x_position; - *arg2 = current_obj->segment.trans.y_position; - *arg3 = current_obj->segment.trans.z_position; + current_obj->behaviorId == BHV_RAMP_SWITCH && current_obj->properties.common.unk0 == timing) { + *x = current_obj->segment.trans.x_position; + *y = current_obj->segment.trans.y_position; + *z = current_obj->segment.trans.z_position; } } } @@ -5496,21 +5585,21 @@ void func_8001E36C(s32 arg0, f32 *arg1, f32 *arg2, f32 *arg3) { /** * Return the index of the currently active cutscene. */ -s16 get_cutscene_id(void) { +s16 cutscene_id(void) { return gCutsceneID; } /** * Set the current cutscene index. */ -void set_cutscene_id(s32 cutsceneID) { +void cutscene_id_set(s32 cutsceneID) { gCutsceneID = cutsceneID; } void func_8001E45C(s32 cutsceneID) { if (cutsceneID != gCutsceneID) { gCutsceneID = cutsceneID; - D_8011ADAC = 0; + gPathUpdateOff = FALSE; D_8011AE7E = 1; if (get_game_mode() == GAMEMODE_MENU) { set_frame_blackout_timer(); @@ -5604,14 +5693,14 @@ void func_8001EE74(void) { } if (D_8011AD26 || animation->channel != 20) { if (obj->unk64 != NULL) { - func_8001EFA4(obj, (Object *) obj->unk64); + obj_init_animcamera(obj, (Object *) obj->unk64); } } } D_8011AD26 = FALSE; } -void func_8001EFA4(Object *arg0, Object *animObj) { +void obj_init_animcamera(Object *arg0, Object *animObj) { LevelObjectEntry_Animation *animEntry; Object_Animation *anim; f32 scale; @@ -5626,10 +5715,10 @@ void func_8001EFA4(Object *arg0, Object *animObj) { animObj->segment.trans.scale = animObj->segment.header->scale * scale; animObj->properties.common.unk0 = 0; animObj->properties.common.unk4 = 0; - if ((animEntry->unk22 >= 2) && (animEntry->unk22 < 10)) { + if (animEntry->unk22 >= 2 && animEntry->unk22 < 10) { animObj->properties.common.unk0 = animEntry->unk22 - 1; } - if ((animEntry->unk22 >= 10) && (animEntry->unk22 < 18)) { + if (animEntry->unk22 >= 10 && animEntry->unk22 < 18) { animObj->properties.common.unk0 = animEntry->unk22 - 9; } animObj->segment.trans.x_position = arg0->segment.trans.x_position; @@ -5642,7 +5731,7 @@ void func_8001EFA4(Object *arg0, Object *animObj) { anim->unk3D = animEntry->channel; anim->unk28 = animEntry->actorIndex; anim->unk8 = (f32) animEntry->nodeSpeed * 0.1; - anim->unk2A = normalise_time(animEntry->animationStartDelay); + anim->startDelay = normalise_time(animEntry->animationStartDelay); animObj->segment.object.animationID = animEntry->objAnimIndex; animObj->segment.animFrame = animEntry->unk16; anim->z = animEntry->objAnimSpeed; @@ -5658,8 +5747,8 @@ void func_8001EFA4(Object *arg0, Object *animObj) { anim->unk2D = 0; anim->unk4 = 0; anim->unk0 = 0; - arg0->unk6C = NULL; - anim->unk36 = normalise_time(animEntry->pauseFrameCount); + arg0->particleEmitter = NULL; + anim->pauseCounter = normalise_time(animEntry->pauseFrameCount); anim->unk3A = animEntry->specialHide; if (animEntry->unk13 >= 0) { anim->unk2F = animEntry->unk13; @@ -5672,9 +5761,9 @@ void func_8001EFA4(Object *arg0, Object *animObj) { anim->unk3C = animEntry->fadeAlpha; anim->unk42 = 0xFF; if (anim->unk18 != NULL) { - func_8000488C(anim->unk18); + sound_stop(anim->unk18); } - anim->unk18 = 0; + anim->unk18 = NULL; anim->unk43 = animEntry->unk30; anim->unk1C = arg0; anim->unk45 = 0; @@ -5693,7 +5782,7 @@ void func_8001F23C(Object *obj, LevelObjectEntry_Animation *animEntry) { obj->unk64 = (Object_64 *) spawn_object((LevelObjectEntryCommon *) &newObjEntry, 1); newObj = (Object *) obj->unk64; // (newObj->behaviorId == BHV_DINO_WHALE) is Dinosaur1, Dinosaur2, Dinosaur3, Whale, and Dinoisle - if ((obj->unk64 != NULL) && (newObj->behaviorId == BHV_DINO_WHALE) && (gTimeTrialEnabled)) { + if (obj->unk64 != NULL && newObj->behaviorId == BHV_DINO_WHALE && gTimeTrialEnabled) { free_object(newObj); obj->unk64 = NULL; newObj = NULL; @@ -5701,7 +5790,7 @@ void func_8001F23C(Object *obj, LevelObjectEntry_Animation *animEntry) { camera = (Object_AnimCamera *) newObj; if (camera != NULL) { camera->unk3C = 0; - func_8001EFA4(obj, newObj); + obj_init_animcamera(obj, newObj); if (newObj->segment.header->behaviorId == BHV_CAMERA_ANIMATION) { camera = &newObj->unk64->anim_camera; camera->unk44 = D_8011AD3E; @@ -5713,10 +5802,10 @@ void func_8001F23C(Object *obj, LevelObjectEntry_Animation *animEntry) { newObj = spawn_object(&newObjEntry, 1); if (newObj != NULL) { newObj->segment.level_entry = NULL; - func_8001EFA4(obj, newObj); + obj_init_animcamera(obj, newObj); camera = &newObj->unk64->anim_camera; i++; - camera->unk30 = i; + camera->cameraID = i; camera->unk44 = D_8011AD3E; } } @@ -5762,9 +5851,9 @@ GLOBAL_ASM("asm/non_matchings/objects/func_8001F460.s") s32 func_800210CC(s8 arg0) { if (arg0 >= D_8011AD3D) { D_8011AD3D = arg0; - return 1; + return TRUE; } - return 0; + return FALSE; } void func_80021104(Object *obj, Object_Animation *animObj, LevelObjectEntry_Animation *entry) { @@ -5777,7 +5866,7 @@ void func_80021104(Object *obj, Object_Animation *animObj, LevelObjectEntry_Anim D_8011AD3E++; } if (entry->unk22 == 18) { - set_active_camera(animObj->unk30); + set_active_camera(animObj->cameraID); seg = get_active_camera_segment_no_cutscenes(); animObjTrans->x_position = seg->trans.x_position; animObjTrans->y_position = seg->trans.y_position; @@ -5881,7 +5970,7 @@ s8 func_800214E4(Object *obj, s32 updateRate) { for (i = 0; (i < D_8011AE78 && animObj->unk28 != D_8011AE74[i]->properties.common.unk4); i++) { if (FALSE) {} // FAKEMATCH } - func_8001EFA4(D_8011AE74[i], obj); + obj_init_animcamera(D_8011AE74[i], obj); return 1; } return 0; @@ -5962,7 +6051,7 @@ UNUSED void func_800228DC(UNUSED s32 arg0, UNUSED s32 arg1, UNUSED s32 arg2) { void init_racer_for_challenge(s32 vehicleID) { Object_Racer *racer; - D_8011AEF7 = 3; + gTajRaceInit = 3; racer = &get_racer_object(PLAYER_ONE)->unk64->racer; racer->courseCheckpoint = 0; racer->checkpoint = 0; @@ -5972,7 +6061,11 @@ void init_racer_for_challenge(s32 vehicleID) { set_pause_lockout_timer(10); } -void func_80022948(void) { +/** + * Initialise the relevant variables related to races. + * These are usually done on level load, but Taj challenges don't reset the level. + */ +void mode_init_taj_race(void) { CheckpointNode *checkpointNode; UNUSED s32 pad; s32 j; @@ -5986,12 +6079,12 @@ void func_80022948(void) { UNUSED s32 pad2[7]; f32 sp2C; - D_8011AEF7 -= 1; - if (D_8011AEF7 == 0) { + gTajRaceInit -= 1; + if (gTajRaceInit == 0) { levelHeader = get_current_level_header(); - D_8011AEF8 = levelHeader->music; - D_8011AEFC = levelHeader->instruments; - levelHeader->music = 0x1D; + gChallengePrevMusic = levelHeader->music; + gChallengePrevInstruments = levelHeader->instruments; + levelHeader->music = SEQUENCE_TAJS_RACES; levelHeader->instruments = 0xFFFF; racerObj = get_racer_object(PLAYER_ONE); racer = &racerObj->unk64->racer; @@ -6013,7 +6106,7 @@ void func_80022948(void) { D_8011ADB4 = 0; D_8011ADC0 = 1; levelHeader->laps = 3; - levelHeader->race_type = 0; + levelHeader->race_type = RACETYPE_DEFAULT; func_8009F034(); // clang-format off for (i = 0; i < ARRAY_COUNT(racer->lap_times); i++) { racer->lap_times[i] = 0; } // Must be a single line. @@ -6041,7 +6134,7 @@ void func_80022948(void) { i = 0; // Fakematch racer->vehicleID = VEHICLE_CARPET; racer->vehicleIDPrev = racer->vehicleID; - racer->unk2 = 1; + racer->racerIndex = 1; racer->characterId = settings->racers[0].character; racer->stretch_height_cap = 1.0f; racer->stretch_height = 1.0f; @@ -6056,35 +6149,42 @@ void func_80022948(void) { } } set_pause_lockout_timer(20); - transition_begin(&D_800DC6F0); + transition_begin(&gTajChallengeTransition); } } -void func_80022CFC(s32 arg0, f32 x, f32 y, f32 z) { - s32 index; - unk80022CFC_1 *obj; +/** + * Finds which golden balloon should be moved, and move it onto Taj's current position. + * Sets opacity to 0, so the balloon with smoothly fade in. + */ +void obj_taj_create_balloon(s32 blockID, f32 x, f32 y, f32 z) { + s32 i; + Object *obj; Settings *settings = get_settings(); - for (index = 0; index < gObjectCount; index += 1) { - obj = ((unk80022CFC_1 *) gObjPtrList[index]); - if (obj->unk48 == 0x4D) { - if (obj->unk3C != NULL) { - if (obj->unk3C->unkA > 0) { - if ((settings->tajFlags != 0) && (settings->tajFlags & (1 << (obj->unk3C->unkA + 2)))) { - obj->unkC = x; - obj->unk10 = y + 10.0; - obj->unk14 = z; - obj->unk2E = arg0; - obj->unk78 = 0; - obj->unk39 = 0; - } - } + for (i = 0; i < gObjectCount; i++) { + obj = gObjPtrList[i]; + if (obj->behaviorId == BHV_GOLDEN_BALLOON && obj->segment.level_entry != NULL && + obj->segment.level_entry->goldenBalloon.challengeID > 0) { + if (settings->tajFlags && + settings->tajFlags & (1 << (obj->segment.level_entry->goldenBalloon.challengeID + 2))) { + obj->segment.trans.x_position = x; + obj->segment.trans.y_position = y + 10.0; + obj->segment.trans.z_position = z; + obj->segment.object.segmentID = blockID; + obj->properties.common.unk0 = 0; + obj->segment.object.opacity = 0; } } } } -void func_80022E18(s32 arg0) { +/** + * Revert changes set by the game when starting the Taj challenge. + * This includes the music set, as well as the extra racer spawned. + * Has a different response depending on whether the challenge was aborted or finished. + */ +void mode_end_taj_race(s32 reason) { s32 flags; s32 i; Object_Racer *racer; @@ -6093,9 +6193,9 @@ void func_80022E18(s32 arg0) { LevelHeader *levelHeader; levelHeader = get_current_level_header(); - levelHeader->race_type = 5; - levelHeader->music = D_8011AEF8; - levelHeader->instruments = D_8011AEFC; + levelHeader->race_type = RACETYPE_HUBWORLD; + levelHeader->music = gChallengePrevMusic; + levelHeader->instruments = gChallengePrevInstruments; minimap_opacity_set(1); // Only works with do {} while? @@ -6114,16 +6214,16 @@ void func_80022E18(s32 arg0) { gNumRacers = 1; for (i = gObjectListStart; i < gObjectCount; i++) { if (!(gObjPtrList[i]->segment.trans.flags & OBJ_FLAGS_DEACTIVATED) && - (gObjPtrList[i]->behaviorId == BHV_PARK_WARDEN)) { + gObjPtrList[i]->behaviorId == BHV_PARK_WARDEN) { obj = gObjPtrList[i]; } } racer = &(*gRacers)[0]->unk64->racer; - if (racer->unk15C != NULL) { - free_object(racer->unk15C); - racer->unk15C = NULL; + if (racer->challengeMarker != NULL) { + free_object(racer->challengeMarker); + racer->challengeMarker = NULL; } - if (arg0 == 0) { + if (reason == CHALLENGE_END_FINISH) { if (racer->finishPosition == 1) { settings = get_settings(); flags = racer->vehicleID; @@ -6138,24 +6238,24 @@ void func_80022E18(s32 arg0) { } else { set_next_taj_challenge_menu(4); } - obj->properties.common.unk0 = 0x1F; + obj->properties.common.unk0 = 31; set_taj_status(2); } else { music_change_on(); music_stop(); set_next_taj_challenge_menu(0); - func_80008168(); - if (arg0 == 2) { + audioline_on(); + if (reason == CHALLENGE_END_OOB) { set_current_text(ASSET_GAME_TEXT_0); } gEventCountdown = 0; gEventStartTimer = 0; - obj->properties.common.unk0 = 0x14; + obj->properties.common.unk0 = 20; } music_change_on(); hud_audio_init(); start_level_music(1.0f); - gIsTajChallenge = 0; + gIsTajChallenge = FALSE; } GLOBAL_ASM("asm/non_matchings/objects/func_800230D0.s") @@ -6210,12 +6310,18 @@ s32 func_80023568(void) { return 0; } -s8 func_800235C0(void) { - return D_8011ADD5; +/** + * Return whether doors can be forced open. + */ +s8 obj_door_override(void) { + return gOverrideDoors; } -void func_800235D0(s32 arg0) { - D_8011ADD5 = arg0; +/** + * Set a value that decides whether doors can be forced open. + */ +void obj_door_open(s32 setting) { + gOverrideDoors = setting; } /** @@ -6233,7 +6339,7 @@ s32 get_object_property_size(Object *obj, Object_64 *obj64) { break; case BHV_DOOR: case BHV_TT_DOOR: - ret = sizeof(Object_TTDoor); + ret = sizeof(Object_Door); break; case BHV_EXIT: ret = sizeof(Object_Exit); @@ -6506,8 +6612,8 @@ void run_object_init_func(Object *obj, void *entry, s32 param) { case BHV_ZIPPER_AIR: obj_init_airzippers_waterzippers(obj, (LevelObjectEntry_AirZippers_WaterZippers *) entry); break; - case BHV_UNK_3A: - obj_init_unknown58(obj, (LevelObjectEntry_Unknown58 *) entry); + case BHV_TIMETRIAL_GHOST: + obj_init_timetrialghost(obj, (LevelObjectEntry_TimeTrial_Ghost *) entry); break; case BHV_WAVE_GENERATOR: obj_init_wavegenerator(obj, (LevelObjectEntry_WaveGenerator *) entry, param); @@ -6902,8 +7008,8 @@ void run_object_loop_func(Object *obj, s32 updateRate) { case BHV_ZIPPER_AIR: obj_loop_airzippers_waterzippers(obj, updateRate); break; - case BHV_UNK_3A: - obj_loop_unknown58(obj, updateRate); + case BHV_TIMETRIAL_GHOST: + obj_loop_timetrialghost(obj, updateRate); break; case BHV_WAVE_POWER: obj_loop_wavepower(obj); diff --git a/src/objects.h b/src/objects.h index e5a3be90..752928d7 100644 --- a/src/objects.h +++ b/src/objects.h @@ -18,6 +18,8 @@ entryVar.objectID = (s8)(entryId); \ } +#define NODE_NONE 255 + enum ObjectBehaviours { BHV_NONE, BHV_RACER, @@ -77,7 +79,7 @@ enum ObjectBehaviours { BHV_TRIGGER, BHV_VEHICLE_ANIMATION, BHV_ZIPPER_WATER, - BHV_UNK_3A, + BHV_TIMETRIAL_GHOST, BHV_WAVE_GENERATOR, BHV_WAVE_POWER, BHV_BUTTERFLY, @@ -187,6 +189,12 @@ enum ContPakErrors { CONTPAK_ERROR_DAMAGED }; +enum TajChallengeReasons { + CHALLENGE_END_FINISH, + CHALLENGE_END_QUIT, + CHALLENGE_END_OOB // out of bounds +}; + typedef struct RacerShieldGfx { s16 x_position; s16 y_position; @@ -353,9 +361,9 @@ s32 get_object_count(void); s32 get_particle_count(void); void func_8000E9D0(Object *arg0); void free_object(Object *); -s32 func_80010018(void); -s32 func_80010028(s32 arg0); -void func_80011390(void); +s32 obj_table_ids(void); +s32 obj_id_valid(s32 arg0); +void path_enable(void); s32 get_race_countdown(void); s32 get_race_start_timer(void); void ignore_bounds_check(void); @@ -372,15 +380,15 @@ u32 func_800179D0(void); void set_taj_challenge_type(s32 vehicleID); s16 get_taj_challenge_type(void); Object *find_taj_object(void); -void func_8001A8D4(s32 arg0); -s16 func_8001AE44(void); +void race_finish_adventure(s32 unusedArg); +s16 race_finish_timer(void); u32 get_balloon_cutscene_timer(void); -s32 func_8001B288(void); -Object *func_8001B2E0(void); -s32 is_time_trial_ghost(Object* obj); -Object *get_time_trial_ghost(void); -s32 unbeaten_staff_time(void); -SIDeviceStatus func_8001B738(s32 controllerIndex); +s32 timetrial_valid_player_ghost(void); +Object *timetrial_player_ghost(void); +s32 timetrial_staff_ghost_check(Object* obj); +Object *timetrial_ghost_staff(void); +s32 timetrial_staff_unbeaten(void); +SIDeviceStatus timetrial_save_player_ghost(s32 controllerIndex); u8 has_ghost_to_save(void); void set_ghost_none(void); f32 func_8001B834(Object_Racer *racer1, Object_Racer *racer2); @@ -392,20 +400,20 @@ Object **get_racer_objects_by_port(s32 *numRacers); Object **get_racer_objects_by_position(s32 *numRacers); Object *get_racer_object(s32 index); void debug_render_checkpoint_node(s32 checkpointID, s32 pathID, Gfx** dList, MatrixS **mtx, Vertex **vtx); -Object *get_camera_object(s32 cameraIndex); -void func_8001D1AC(void); -void func_8001D1BC(s32 arg0); -Object *func_8001D1E4(s32 *arg0); -Object *func_8001D214(s32 arg0); +Object *spectate_object(s32 cameraIndex); +void ainode_enable(void); +void ainode_tail_set(s32 nodeID); +Object *ainode_tail(s32 *nodeID); +Object *ainode_get(s32 nodeID); void set_world_shading(f32 brightness, f32 ambient, s16 angleX, s16 angleY, s16 angleZ); void set_shading_properties(ShadeProperties *arg0, f32 brightness, f32 ambient, s16 angleX, s16 angleY, s16 angleZ); void calc_dyn_light_and_env_map_for_object(ObjectModel *model, Object *object, s32 arg2, f32 intensity); s32 *get_misc_asset(s32 index); s32 func_8001E2EC(s32 arg0); void func_8001E344(s32 arg0); -void func_8001E36C(s32 arg0, f32 *arg1, f32 *arg2, f32 *arg3); -s16 get_cutscene_id(void); -void set_cutscene_id(s32 cutsceneID); +void obj_bridge_pos(s32 timing, f32 *x, f32 *y, f32 *z); +s16 cutscene_id(void); +void cutscene_id_set(s32 cutsceneID); void func_8001E45C(s32 cutsceneID); s32 get_object_list_index(void); s8 func_8001F3B8(void); @@ -418,8 +426,8 @@ void func_800228DC(s32 arg0, s32 arg1, s32 arg2); void init_racer_for_challenge(s32 vehicleID); s8 is_taj_challenge(void); s32 func_80023568(void); -s8 func_800235C0(void); -void func_800235D0(s32 arg0); +s8 obj_door_override(void); +void obj_door_open(s32 setting); void run_object_init_func(Object *obj, void *entry, s32 param); void run_object_loop_func(Object *obj, s32 updateRate); s16 *func_80024594(s32 *currentCount, s32 *maxCount); @@ -427,23 +435,23 @@ void func_800245B4(s16 arg0); void object_do_player_tumble(Object *this); f32 catmull_rom_interpolation(f32 *data, s32 index, f32 x); f32 cubic_spline_interpolation(f32 *data, s32 index, f32 x, f32 *derivative); -s16 func_8001C418(f32 yPos); +s16 obj_elevation(f32 yPos); void func_80021400(s32 arg0); -s32 func_8001B668(s32 arg0); +s32 timetrial_init_player_ghost(s32 playerID); s32 move_object(Object *obj, f32 xPos, f32 yPos, f32 zPos); Object *get_racer_object_by_port(s32 index); void render_racer_shield(Gfx **dList, MatrixS **mtx, Vertex **vtxList, Object *obj); void render_racer_magnet(Gfx **dList, MatrixS **mtx, Vertex **vtxList, Object *obj); void update_envmap_position(f32 x, f32 y, f32 z); s32 init_object_water_effect(Object *obj, WaterEffect *waterEffect); -s32 func_8001B2F0(s32 mapId); +s32 timetrial_load_staff_ghost(s32 mapId); void render_3d_billboard(Object *obj); void render_misc_model(Object *obj, Vertex *verts, u32 numVertices, Triangle *triangles, u32 numTriangles, TextureHeader *tex, u32 flags, u32 texOffset, f32 scale); void func_8000B290(void); void func_80016BC4(Object *obj); -s32 func_8001C48C(Object *obj); -void func_80022CFC(s32 arg0, f32 x, f32 y, f32 z); +s32 ainode_register(Object *obj); +void obj_taj_create_balloon(s32 blockID, f32 x, f32 y, f32 z); Object *func_8001B7A8(Object *racer, s32 position, f32 *distance); s32 func_8000FD34(Object *obj, Object_5C *matrices); void func_8000E4E8(s32 index); @@ -451,7 +459,7 @@ void objFreeAssets(Object *obj, s32 count, s32 objType); void func_8001709C(Object *obj); s32 play_footstep_sounds(Object *obj, s32 arg1, s32 frame, s32 oddSoundId, s32 evenSoundId); void render_3d_misc(Object *obj); -Object *find_nearest_spectate_camera(Object *obj, s32 *cameraId); +Object *spectate_nearest(Object *obj, s32 *cameraId); s32 init_object_shadow(Object *obj, ShadowData *shadow); s32 render_mesh(ObjectModel *objModel, Object *obj, s32 startIndex, s32 flags, s32 someBool); void render_bubble_trap(ObjectTransform *trans, Object_68 *gfxData, Object *obj, s32 flags); @@ -463,32 +471,32 @@ void try_free_object_header(s32 index); s32 get_object_property_size(Object *obj, Object_64 *obj64); void light_setup_light_sources(Object *obj); s32 init_object_interaction_data(Object *obj, ObjectInteraction *interactObj); -s32 func_8000FAC4(Object *obj, Object_6C *arg1); +s32 obj_init_emitter(Object *obj, ParticleEmitter *emitter); s32 obj_init_property_flags(s32 behaviorId); void tt_ghost_beaten(s32 arg0, s16 *playerId); -void func_8001EFA4(Object *, Object *); -Object *func_80016C68(f32 x, f32 y, f32 z, f32 maxDistCheck, s32 dontCheckYAxis); +void obj_init_animcamera(Object *, Object *); +Object *obj_butterfly_node(f32 x, f32 y, f32 z, f32 maxDistCheck, s32 dontCheckYAxis); void func_8002125C(Object *charSelectObj, LevelObjectEntry_CharacterSelect *entry, Object_CharacterSelect *charSelect, UNUSED s32 index); void func_80021104(Object *obj, Object_Animation *animObj, LevelObjectEntry_Animation *entry); s32 func_8001955C(Object *obj, s32 checkpoint, u8 arg2, s32 arg3, s32 arg4, f32 checkpointDist, f32 *outX, f32 *outY, f32 *outZ); void func_80016500(Object *obj, Object_Racer *racer); void func_8000C8F8(s32, s32); -u8 func_8001B4FC(s32 trackId); +u8 timetrial_init_staff_ghost(s32 trackId); s8 set_course_finish_flags(Settings *settings); void process_object_interactions(void); void render_3d_model(Object *obj); -void func_80022E18(s32 arg0); -void func_8001BF20(void); +void mode_end_taj_race(s32 reason); +void ainode_update(void); void func_8001E6EC(s8); Object *func_8000FD54(s32 objectHeaderIndex); void sort_objects_by_dist(s32 startIndex, s32 lastIndex); void func_80016748(Object *obj0, Object *obj1); -void func_8001AE64(void); -s32 func_80016DE8(f32 x, f32 y, f32 z, f32 radius, s32 is2dCheck, Object **arg5); -void func_80022948(void); +void race_finish_time_trial(void); +s32 obj_dist_racer(f32 x, f32 y, f32 z, f32 radius, s32 is2dCheck, Object **sortObj); +void mode_init_taj_race(void); void func_8000BADC(s32 updateRate); f32 func_8002277C(f32 *data, s32 index, f32 x); -void func_8001A8F4(s32 updateRate); +void race_transition_adventure(s32 updateRate); //Non Matching void calc_dynamic_lighting_for_object_1(Object *, ObjectModel *, s16, Object *, f32, f32); @@ -509,7 +517,7 @@ void func_800135B8(Object *); void func_8000CC7C(Vehicle, u32, s32); void func_8000B020(s32, s32); void func_80017E98(void); -void func_8001BC54(void); +void spectate_update(void); void func_8001E93C(void); void func_80019808(s32 updateRate); void func_80014090(Object*, s32, ObjectHeader*); diff --git a/src/particles.c b/src/particles.c index 025e3e60..6e156979 100644 --- a/src/particles.c +++ b/src/particles.c @@ -522,7 +522,7 @@ void func_800AF52C(Object *obj, s32 arg1) { ParticleBehavior *behaviour; Particle *temp; - temp_v0 = (Particle *) &obj->unk6C[arg1]; + temp_v0 = (Particle *) &obj->particleEmitter[arg1].unk0; behaviour = temp_v0->data.behaviour; temp_v0->data.opacity = 0; if (temp_v0->data.flags & 0x4000) { @@ -566,9 +566,9 @@ void func_800AF52C(Object *obj, s32 arg1) { } void func_800AF6E4(Object *obj, s32 arg1) { - Object_6C *obj6C; + ParticleEmitter *obj6C; - obj6C = &obj->unk6C[arg1]; + obj6C = &obj->particleEmitter[arg1]; obj6C->unk4 &= 0x7FFF; obj->segment.unk1A--; @@ -580,8 +580,8 @@ void func_800AF714(Object *racerObj, s32 updateRate) { s32 var_v0; s32 temp_v1; s32 i; - Object_6C *new_var; - Object_6C *new_var2; + ParticleEmitter *new_var; + ParticleEmitter *new_var2; s32 var_t1; s32 someBool; s8 vehicleId; @@ -589,12 +589,12 @@ void func_800AF714(Object *racerObj, s32 updateRate) { u8 *alphaPtr; racer = &racerObj->unk64->racer; - var_s7 = racerObj->unk74; + var_s7 = racerObj->particleEmitFlags; vehicleId = racer->vehicleID; i = 0; object_do_player_tumble(racerObj); - for (; i < racerObj->segment.header->unk57; i++) { - if (var_s7 & 1) { + for (; i < racerObj->segment.header->particleCount; i++) { + if (var_s7 & OBJ_EMIT_PARTICLE_1) { someBool = TRUE; switch (vehicleId) { case VEHICLE_CAR: @@ -605,7 +605,7 @@ void func_800AF714(Object *racerObj, s32 updateRate) { } var_v0 -= 24; if (var_v0 > 0) { - temp_a3 = gParticlesAssetTable[racerObj->unk6C[i].unk8]; + temp_a3 = gParticlesAssetTable[racerObj->particleEmitter[i].unk8]; alphaPtr = &D_800E2EC4[i].a; var_t1 = 4; if (var_v0 > 32) { @@ -666,41 +666,41 @@ void func_800AF714(Object *racerObj, s32 updateRate) { break; case VEHICLE_HOVERCRAFT: if (i == 2 || i == 3) { - var_v0 = D_80127C88[racer->unk2 & 7]; + var_v0 = D_80127C88[racer->racerIndex & 7]; var_v0 += (updateRate * 4); if (var_v0 > 256) { var_v0 = 256; } - D_80127C88[racer->unk2 & 7] = var_v0; + D_80127C88[racer->racerIndex & 7] = var_v0; gParticleOpacity = var_v0; } break; } if (someBool) { - if (!(racerObj->unk6C[i].unk4 & 0x8000)) { + if (!(racerObj->particleEmitter[i].unk4 & 0x8000)) { func_800AF52C(racerObj, i); } - if (racerObj->unk6C[i].unk4 & 0x4000) { - func_800AFE5C((Particle *) racerObj, (Particle *) &racerObj->unk6C[i]); - } else if (racerObj->unk6C[i].unk4 & 0x400) { - func_800AFE5C((Particle *) racerObj, (Particle *) &racerObj->unk6C[i]); + if (racerObj->particleEmitter[i].unk4 & 0x4000) { + func_800AFE5C((Particle *) racerObj, (Particle *) &racerObj->particleEmitter[i]); + } else if (racerObj->particleEmitter[i].unk4 & 0x400) { + func_800AFE5C((Particle *) racerObj, (Particle *) &racerObj->particleEmitter[i]); } else { - racerObj->unk6C[i].unkA += updateRate; - if (racerObj->unk6C[i].unkA >= racerObj->unk6C[i].unk0->segment.unk40_s16) { - func_800AFE5C((Particle *) racerObj, (Particle *) &racerObj->unk6C[i]); + racerObj->particleEmitter[i].unkA += updateRate; + if (racerObj->particleEmitter[i].unkA >= racerObj->particleEmitter[i].unk0->segment.unk40_s16) { + func_800AFE5C((Particle *) racerObj, (Particle *) &racerObj->particleEmitter[i]); } } } - } else if (racerObj->unk6C[i].unk4 & 0x8000) { - if (racerObj->unk6C[i].unk4 & 0x4000) { - new_var2 = &racerObj->unk6C[i]; + } else if (racerObj->particleEmitter[i].unk4 & 0x8000) { + if (racerObj->particleEmitter[i].unk4 & 0x4000) { + new_var2 = &racerObj->particleEmitter[i]; new_var2->unk6 = 0; func_800AF6E4(racerObj, i); } else { - if (racerObj->unk6C[i].unk4 & 0x400) { - new_var = &racerObj->unk6C[i]; - racerObj->unk6C[i].unk4 |= 0x200; + if (racerObj->particleEmitter[i].unk4 & 0x400) { + new_var = &racerObj->particleEmitter[i]; + racerObj->particleEmitter[i].unk4 |= 0x200; if (new_var->unk6 == 0) { func_800AF6E4(racerObj, i); } @@ -709,7 +709,7 @@ void func_800AF714(Object *racerObj, s32 updateRate) { } } if (i == 2 || i == 3) { - D_80127C88[racer->unk2 & 7] = 0; + D_80127C88[racer->racerIndex & 7] = 0; } } D_800E2D00[0].word = 0; @@ -720,37 +720,37 @@ void func_800AF714(Object *racerObj, s32 updateRate) { object_undo_player_tumble(racerObj); } -void func_800AFC3C(Object *obj, s32 updateRate) { - Object_6C *temp_s1; - Object_6C *temp_s1_2; +void obj_spawn_particle(Object *obj, s32 updateRate) { + ParticleEmitter *temp_s1; + ParticleEmitter *temp_s1_2; s32 var_s0; s32 i; UNUSED s32 pad; s32 var_a3; u32 bits; - bits = obj->unk74; - var_a3 = obj->segment.header->unk57; + bits = obj->particleEmitFlags; + var_a3 = obj->segment.header->particleCount; for (i = 0; i < var_a3; i++) { if (bits & 1) { - if (!(obj->unk6C[i].unk4 & 0x8000)) { + if (!(obj->particleEmitter[i].unk4 & 0x8000)) { func_800AF52C(obj, i); } - if (obj->unk6C[i].unk4 & 0x4000) { - func_800AFE5C((Particle *) obj, (Particle *) &obj->unk6C[i]); - } else if ((obj->unk6C[i].unk4 & 0x400)) { - func_800AFE5C((Particle *) obj, (Particle *) &obj->unk6C[i]); + if (obj->particleEmitter[i].unk4 & 0x4000) { + func_800AFE5C((Particle *) obj, (Particle *) &obj->particleEmitter[i]); + } else if ((obj->particleEmitter[i].unk4 & 0x400)) { + func_800AFE5C((Particle *) obj, (Particle *) &obj->particleEmitter[i]); } else { - obj->unk6C[i].unkA += updateRate; - if (obj->unk6C[i].unkA >= obj->unk6C[i].unk0->segment.unk40_s16) { - func_800AFE5C((Particle *) obj, (Particle *) &obj->unk6C[i]); + obj->particleEmitter[i].unkA += updateRate; + if (obj->particleEmitter[i].unkA >= obj->particleEmitter[i].unk0->segment.unk40_s16) { + func_800AFE5C((Particle *) obj, (Particle *) &obj->particleEmitter[i]); } } - var_a3 = obj->segment.header->unk57; + var_a3 = obj->segment.header->particleCount; } else { - if (obj->unk6C[i].unk4 & 0x8000) { - if (obj->unk6C[i].unk4 & 0x4000) { - temp_s1 = &obj->unk6C[i]; + if (obj->particleEmitter[i].unk4 & 0x8000) { + if (obj->particleEmitter[i].unk4 & 0x4000) { + temp_s1 = &obj->particleEmitter[i]; var_s0 = temp_s1->unk6 - 0x40; if (var_s0 < 0) { var_s0 = 0; @@ -761,17 +761,17 @@ void func_800AFC3C(Object *obj, s32 updateRate) { if (var_s0 == 0) { func_800AF6E4(obj, i); } - var_a3 = obj->segment.header->unk57; - } else if ((obj->unk6C[i].unk4 & 0x400)) { - temp_s1_2 = &obj->unk6C[i]; - obj->unk6C[i].unk4 |= 0x200; + var_a3 = obj->segment.header->particleCount; + } else if ((obj->particleEmitter[i].unk4 & 0x400)) { + temp_s1_2 = &obj->particleEmitter[i]; + obj->particleEmitter[i].unk4 |= 0x200; if (temp_s1_2->unk6 == 0) { func_800AF6E4(obj, i); } - var_a3 = obj->segment.header->unk57; + var_a3 = obj->segment.header->particleCount; } else { func_800AF6E4(obj, i); - var_a3 = obj->segment.header->unk57; + var_a3 = obj->segment.header->particleCount; } } } @@ -779,7 +779,7 @@ void func_800AFC3C(Object *obj, s32 updateRate) { } } -// TODO: Should this be void func_800AFE5C(Object *arg0, Object_6C *arg1)? +// TODO: Should this be void func_800AFE5C(Object *arg0, ParticleEmitter *arg1)? void func_800AFE5C(Particle *arg0, Particle *arg1) { Particle *temp_s0; Particle *tempObj; @@ -2319,24 +2319,24 @@ void func_800B4668(Object *obj, s32 idx, s32 arg2, s32 arg3) { s32 temp_v0; arg3 <<= 8; - temp_v0 = (obj->unk6C[idx].unkA & 0xFFFF) + arg2; + temp_v0 = (obj->particleEmitter[idx].unkA & 0xFFFF) + arg2; if (arg3 < temp_v0) { - obj->unk6C[idx].unkA = arg3; + obj->particleEmitter[idx].unkA = arg3; } else { - obj->unk6C[idx].unkA = temp_v0; + obj->particleEmitter[idx].unkA = temp_v0; } - obj->unk6C[idx].unk4 |= 0x100; + obj->particleEmitter[idx].unk4 |= 0x100; } void func_800B46BC(Object *obj, s32 idx, s32 arg2, s32 arg3) { s32 temp_v0; arg3 <<= 8; - temp_v0 = (obj->unk6C[idx].unkA & 0xFFFF) - arg2; + temp_v0 = (obj->particleEmitter[idx].unkA & 0xFFFF) - arg2; if (temp_v0 < arg3) { - obj->unk6C[idx].unkA = arg3; + obj->particleEmitter[idx].unkA = arg3; } else { - obj->unk6C[idx].unkA = temp_v0; + obj->particleEmitter[idx].unkA = temp_v0; } - obj->unk6C[idx].unk4 |= 0x100; + obj->particleEmitter[idx].unk4 |= 0x100; } diff --git a/src/particles.h b/src/particles.h index c84ee99a..ed1c7eeb 100644 --- a/src/particles.h +++ b/src/particles.h @@ -5,6 +5,26 @@ #include "structs.h" #include "libultra_internal.h" +enum ObjectEmitterFlags { + OBJ_EMIT_OFF, + OBJ_EMIT_PARTICLE_1 = (1 << 0), + OBJ_EMIT_PARTICLE_2 = (1 << 1), + OBJ_EMIT_PARTICLE_3 = (1 << 2), + OBJ_EMIT_PARTICLE_4 = (1 << 3), + OBJ_EMIT_UNK_10 = (1 << 4), + OBJ_EMIT_UNK_20 = (1 << 5), + OBJ_EMIT_UNK_40 = (1 << 6), + OBJ_EMIT_UNK_80 = (1 << 7), + OBJ_EMIT_UNK_100 = (1 << 8), + OBJ_EMIT_UNK_200 = (1 << 9), + OBJ_EMIT_UNK_400 = (1 << 10), + OBJ_EMIT_UNK_800 = (1 << 11), + OBJ_EMIT_UNK_1000 = (1 << 12), + OBJ_EMIT_UNK_2000 = (1 << 13), + OBJ_EMIT_UNK_4000 = (1 << 14), + OBJ_EMIT_UNK_8000 = (1 << 15), +}; + enum ParticleFlags { PARTICLE_FLAGS_NONE, PARTICLE_GRAVITY = (1 << 0), @@ -305,7 +325,7 @@ void func_800AF134(Particle *particle, s32 behaviourID, s32 propertyID, s16 velX void render_particle(Particle *particle, Gfx **dList, MatrixS **mtx, Vertex **vtx, s32 flags); void func_800B4668(Object *obj, s32 idx, s32 arg2, s32 arg3); void func_800B46BC(Object *obj, s32 idx, s32 arg2, s32 arg3); -void func_800AFC3C(Object *obj, s32 updateRate); +void obj_spawn_particle(Object *obj, s32 updateRate); void func_800B3E64(Object *obj); void func_800B26E0(Particle *particle); void func_800AF714(Object *racerObj, s32 updateRate); diff --git a/src/racer.c b/src/racer.c index a31f9c3d..fef81f60 100644 --- a/src/racer.c +++ b/src/racer.c @@ -161,12 +161,12 @@ s16 gDialogueCameraAngle; s8 gEggChallengeFlags[4]; s8 D_8011D58C[4]; GhostNode *gGhostData[3]; -s8 D_8011D59C; -s8 D_8011D59D; -s16 D_8011D59E; -s16 D_8011D5A0[3]; // gTTGhostNodeCount? -s16 D_8011D5A8[2]; -s16 D_8011D5AC; // Previous MapId? +s8 gCurrentGhostIndex; +s8 gPrevGhostNodeIndex; +s16 gGhostNodeDelay; +s16 gGhostNodeCount[3]; +s16 gGhostNodeFull[2]; +s16 gGhostMapID; // Previous MapId? s8 gRacerWaveCount; s8 D_8011D5AF; WaterProperties **gRacerCurrentWave; @@ -221,7 +221,7 @@ void func_80042D20(Object *obj, Object_Racer *racer, s32 updateRate) { } else { racer->unk1C6 = 0; } - if (func_8001AE44() != 0) { + if (race_finish_timer() != 0) { gCurrentRacerInput |= A_BUTTON; } else { index = 0; @@ -308,7 +308,7 @@ void func_80042D20(Object *obj, Object_Racer *racer, s32 updateRate) { if ((f32) (s16) ((racer->aiSkill - 2) << 2) <= 300.0f - D_8011D544) { gCurrentRacerInput |= A_BUTTON; } - miscAsset4 = (u8 *) get_misc_asset(ASSET_MISC_12); + miscAsset4 = (u8 *) get_misc_asset(ASSET_MISC_BALLOON_DATA); if (racer->balloon_level < 3) { balloonType = miscAsset4[racer->balloon_type * 3 + racer->balloon_level]; } else { @@ -555,7 +555,7 @@ void increment_ai_behaviour_chances(Object *obj, Object_Racer *racer, s32 update } else { sBalloonLevelAI = 0; } - test = (s8 *) get_misc_asset(ASSET_MISC_12); + test = (s8 *) get_misc_asset(ASSET_MISC_BALLOON_DATA); if ((gCurrentButtonsReleased & Z_TRIG) && racer->balloon_quantity) { if (racer->balloon_level < 3) { balloonType = test[racer->balloon_type * 3 + racer->balloon_level]; @@ -625,7 +625,7 @@ void racer_AI_pathing_inputs(Object *obj, Object_Racer *racer, s32 updateRate) { racer->unk1CA = (racer->unk1CA + 1) & 3; } else if (raceType == RACETYPE_CHALLENGE_BATTLE || raceType == RACETYPE_CHALLENGE_BANANAS) { if (racer->unk1CE != 0xFF) { - racer->unk154 = func_8001D214(racer->unk1CE); + racer->unk154 = ainode_get(racer->unk1CE); } } } @@ -728,7 +728,7 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r sp67 = 0; if (racer->playerIndex >= PLAYER_ONE && gNumViewports < 2) { - obj->unk74 |= 0x100; + obj->particleEmitFlags |= 0x100; } D_8011D550 = 0; @@ -1017,7 +1017,7 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r } } else if (racer->approachTarget == 0) { racer_play_sound(obj, SOUND_UNK_AF); - obj->unk74 |= 0x30; + obj->particleEmitFlags |= 0x30; } temp_f2 = racer->trickType - 5.0f; if ((temp_f2 > 0.0f) && (racer->approachTarget == 0)) { @@ -1281,7 +1281,7 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r if (racer->buoyancy > 0.0 && racer->unk1FB == 0 && obj->segment.y_velocity > 4.0) { obj->segment.y_velocity = 4.0f; } - if (gNumViewports < 2 && obj->segment.header->unk57 >= 9) { + if (gNumViewports < 2 && obj->segment.header->particleCount >= 9) { if ((gCurrentRacerInput & (A_BUTTON | R_TRIG)) == (A_BUTTON | R_TRIG) && (gCurrentStickX < -30 || gCurrentStickX > 30)) { func_800B4668(obj, 8, updateRate << 10, 0x80); @@ -1296,13 +1296,13 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r (obj->segment.z_velocity * obj->segment.z_velocity); if (temp_f2 > 16.0f) { if (temp_f2 < 80.0f) { - obj->unk74 |= 0x8 | 0x4; + obj->particleEmitFlags |= 0x8 | 0x4; } if (temp_f2 > 28.0f) { - obj->unk74 |= 3; + obj->particleEmitFlags |= 3; } if ((gNumViewports == 1) && (temp_f2 > 10.25f)) { - obj->unk74 |= 0x40; + obj->particleEmitFlags |= 0x40; } } } else { @@ -1312,25 +1312,25 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r var_f2 = racer->velocity; } if (var_f2 > 4.0f) { - obj->unk74 |= 0xC; + obj->particleEmitFlags |= 0xC; } } } if (gCurrentPlayerIndex != PLAYER_COMPUTER && racer->boostTimer == 0 && gNumViewports < 2) { - asset20 = &((Asset20 *) get_misc_asset(ASSET_MISC_20))[racer->unk2]; + asset20 = &((Asset20 *) get_misc_asset(ASSET_MISC_20))[racer->racerIndex]; i = ((racer->boostType & EMPOWER_BOOST) >> 2) + 10; if (i > 10) { if (asset20->unk70 > 0 || asset20->unk74 > 0.0) { - obj->unk74 |= 1 << i; + obj->particleEmitFlags |= 1 << i; } } else if (asset20->unk70 == 2 && asset20->unk74 < 0.5) { - obj->unk74 |= 1 << i; + obj->particleEmitFlags |= 1 << i; } else if (asset20->unk70 < 2 && asset20->unk74 > 0.0f) { - obj->unk74 |= 1 << i; + obj->particleEmitFlags |= 1 << i; } } if (racer->unk201 == 0) { - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; } else { obj->segment.y_velocity += updateRate * gCurrentRacerWeightStat; func_800AF714(obj, updateRate); @@ -2247,7 +2247,7 @@ void update_player_racer(Object *obj, s32 updateRate) { if (tempRacer->unk1F6 < 0) { tempRacer->unk1F6 = 0; } - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; if (tempRacer->unk201 > 0) { tempRacer->unk201 -= updateRate; } else { @@ -2498,7 +2498,7 @@ void update_player_racer(Object *obj, s32 updateRate) { } if (tempRacer->magnetTimer == 0) { if (tempRacer->magnetSoundMask) { - func_8000488C(tempRacer->magnetSoundMask); + sound_stop(tempRacer->magnetSoundMask); tempRacer->magnetSoundMask = NULL; } } @@ -2546,28 +2546,34 @@ void update_player_racer(Object *obj, s32 updateRate) { if (is_taj_challenge()) { if (gCurrentPlayerIndex != PLAYER_COMPUTER) { checkpointNode = find_next_checkpoint_node(tempRacer->checkpoint, tempRacer->unk1C8); - if (!tempRacer->unk15C) { + if (!tempRacer->challengeMarker) { newObject.x = 0; newObject.y = 0; newObject.z = 0; newObject.objectID = ASSET_OBJECT_ID_CHECKARROW; newObject.size = 8; - tempRacer->unk15C = spawn_object(&newObject, 1); - if (tempRacer->unk15C) { - tempRacer->unk15C->segment.level_entry = NULL; - tempRacer->unk15C->segment.object.opacity = 128; + tempRacer->challengeMarker = spawn_object(&newObject, 1); + if (tempRacer->challengeMarker) { + tempRacer->challengeMarker->segment.level_entry = NULL; + tempRacer->challengeMarker->segment.object.opacity = 128; } } - if (tempRacer->unk15C) { - tempRacer->unk15C->segment.trans.x_position = checkpointNode->obj->segment.trans.x_position; - tempRacer->unk15C->segment.trans.y_position = checkpointNode->obj->segment.trans.y_position; + if (tempRacer->challengeMarker) { + tempRacer->challengeMarker->segment.trans.x_position = + checkpointNode->obj->segment.trans.x_position; + tempRacer->challengeMarker->segment.trans.y_position = + checkpointNode->obj->segment.trans.y_position; if (tempRacer->vehicleID == VEHICLE_CAR) { - tempRacer->unk15C->segment.trans.y_position -= 30.0; + tempRacer->challengeMarker->segment.trans.y_position -= 30.0; } - tempRacer->unk15C->segment.trans.z_position = checkpointNode->obj->segment.trans.z_position; - tempRacer->unk15C->segment.trans.y_rotation = checkpointNode->obj->segment.trans.y_rotation; - tempRacer->unk15C->segment.trans.x_rotation = checkpointNode->obj->segment.trans.x_rotation; - tempRacer->unk15C->segment.object.segmentID = checkpointNode->obj->segment.object.segmentID; + tempRacer->challengeMarker->segment.trans.z_position = + checkpointNode->obj->segment.trans.z_position; + tempRacer->challengeMarker->segment.trans.y_rotation = + checkpointNode->obj->segment.trans.y_rotation; + tempRacer->challengeMarker->segment.trans.x_rotation = + checkpointNode->obj->segment.trans.x_rotation; + tempRacer->challengeMarker->segment.object.segmentID = + checkpointNode->obj->segment.object.segmentID; } } } @@ -2582,11 +2588,11 @@ void update_player_racer(Object *obj, s32 updateRate) { tempRacer->unk1A8 = tempVar; } if (is_taj_challenge()) { - if (tempRacer->unk15C) { - tempRacer->unk15C->segment.animFrame += 8 * updateRate; + if (tempRacer->challengeMarker) { + tempRacer->challengeMarker->segment.animFrame += 8 * updateRate; } if (tempRacer->unk1BA > 400 || tempRacer->unk1BA < -400) { - func_80022E18(2); + mode_end_taj_race(CHALLENGE_END_OOB); } } func_80018CE0(obj, xTemp, yTemp, zTemp, updateRate); @@ -2622,11 +2628,15 @@ void update_player_racer(Object *obj, s32 updateRate) { tempVar = ((tempRacer->headAngleTarget - tempRacer->headAngle) * updateRate) >> 3; CLAMP(tempVar, -0x800, 0x800); +#ifdef ANTI_TAMPER if (gAntiPiracyHeadroll) { tempRacer->headAngle += gAntiPiracyHeadroll; } else { tempRacer->headAngle += tempVar; } +#else + tempRacer->headAngle += tempVar; +#endif if ((gCurrentButtonsPressed & R_TRIG) && tempRacer->tapTimerR) { tempRacer->tappedR = TRUE; tempRacer->tapTimerR = 0; @@ -2661,7 +2671,7 @@ void update_player_racer(Object *obj, s32 updateRate) { obj->segment.trans.y_position, obj->segment.trans.z_position); } if (is_in_time_trial() && tempRacer->playerIndex == PLAYER_ONE && gRaceStartTimer == 0) { - func_80059BF0(obj, updateRate); + timetrial_ghost_write(obj, updateRate); } if (tempRacer->soundMask) { update_spatial_audio_position(tempRacer->soundMask, obj->segment.trans.x_position, @@ -2704,9 +2714,9 @@ void update_player_racer(Object *obj, s32 updateRate) { } } if (header->race_type & RACETYPE_CHALLENGE && header->race_type != RACETYPE_CHALLENGE_EGGS) { - tempRacer->unk212 = func_8001C418(obj->segment.trans.y_position); + tempRacer->elevation = obj_elevation(obj->segment.trans.y_position); } else { - tempRacer->unk212 = 0; + tempRacer->elevation = ELEVATION_LOW; } if (tempRacer->countLap < tempRacer->lap) { tempRacer->countLap = tempRacer->lap; @@ -2911,11 +2921,11 @@ void func_80050A28(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR if (gCurrentPlayerIndex >= PLAYER_ONE) { if (gNumViewports < FOUR_PLAYERS) { if (racer->drift_direction > 0) { - obj->unk74 |= 0x1000 | 0x400; + obj->particleEmitFlags |= 0x1000 | 0x400; } else if (racer->drift_direction < 0) { - obj->unk74 |= 0x2000 | 0x800; + obj->particleEmitFlags |= 0x2000 | 0x800; } else { - obj->unk74 |= 0x2000 | 0x1000; + obj->particleEmitFlags |= 0x2000 | 0x1000; } } else { sp58 = 1; @@ -2942,7 +2952,7 @@ void func_80050A28(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR gCurrentStickY = -70; sp60 = TRUE; if (gNumViewports < FOUR_PLAYERS) { - obj->unk74 |= 0x2000 | 0x1000 | 0x800 | 0x400; + obj->particleEmitFlags |= 0x2000 | 0x1000 | 0x800 | 0x400; } else { sp58 = 1; } @@ -2967,9 +2977,9 @@ void func_80050A28(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR if (racer->drift_direction != 0 && gCurrentPlayerIndex >= PLAYER_ONE) { if (gNumViewports < FOUR_PLAYERS) { if (racer->drift_direction > 0) { - obj->unk74 |= 0x1000 | 0x400; + obj->particleEmitFlags |= 0x1000 | 0x400; } else { - obj->unk74 |= 0x2000 | 0x800; + obj->particleEmitFlags |= 0x2000 | 0x800; } } else { sp58 = 1; @@ -3015,9 +3025,9 @@ void func_80050A28(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR rumble_set(racer->playerIndex, RUMBLE_TYPE_0); } if (racer->y_rotation_vel < 0) { - obj->unk74 |= 0x1000 | 0x400; + obj->particleEmitFlags |= 0x1000 | 0x400; } else { - obj->unk74 |= 0x2000 | 0x800; + obj->particleEmitFlags |= 0x2000 | 0x800; } if (racer->drift_direction != 0 || racer->drifting != 0 || racer->unk1FB != 0) { if (racer->unk10 == 0) { @@ -3028,19 +3038,19 @@ void func_80050A28(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR obj->segment.trans.z_position); } if (racer->unk14) { - func_8000488C(racer->unk14); + sound_stop(racer->unk14); } } else { if (racer->unk10) { - func_8000488C(racer->unk10); + sound_stop(racer->unk10); } } } else { if (racer->unk10) { - func_8000488C(racer->unk10); + sound_stop(racer->unk10); } if (racer->unk14) { - func_8000488C(racer->unk14); + sound_stop(racer->unk14); } } // Velocity of steering input @@ -3190,18 +3200,18 @@ void func_80050A28(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR if (get_viewport_count() < THREE_PLAYERS) { if ((sp60 && racer->velocity < -2.0) || sp58 || racer->unk1FB != 0) { if (racer->wheel_surfaces[2] < SURFACE_NONE) { - obj->unk74 |= gSurfaceFlagTable[racer->wheel_surfaces[2]]; + obj->particleEmitFlags |= gSurfaceFlagTable[racer->wheel_surfaces[2]]; } if (racer->wheel_surfaces[3] < SURFACE_NONE) { - obj->unk74 |= gSurfaceFlagTable[racer->wheel_surfaces[3]] * 2; + obj->particleEmitFlags |= gSurfaceFlagTable[racer->wheel_surfaces[3]] * 2; } } if (racer->velocity < -2.0) { if (racer->wheel_surfaces[2] < SURFACE_NONE) { - obj->unk74 |= gSurfaceFlagTable4P[racer->wheel_surfaces[2]]; + obj->particleEmitFlags |= gSurfaceFlagTable4P[racer->wheel_surfaces[2]]; } if (racer->wheel_surfaces[3] < SURFACE_NONE) { - obj->unk74 |= gSurfaceFlagTable4P[racer->wheel_surfaces[3]] * 2; + obj->particleEmitFlags |= gSurfaceFlagTable4P[racer->wheel_surfaces[3]] * 2; } } } @@ -3212,7 +3222,7 @@ void func_80050A28(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR sound_play(soundID, &racer->unk18); } if (racer->unk18 != NULL && (soundID == SOUND_NONE || racer->velocity > -2.0)) { - func_8000488C(racer->unk18); + sound_stop(racer->unk18); } // Apply a bobbing effect when on grass and sand. if (racer->velocity < -2.0 && sp68 >= 4) { @@ -3435,7 +3445,7 @@ void func_8005250C(Object *obj, Object_Racer *racer, s32 updateRate) { angleVel = 0; if (racer->balloon_quantity > 0) { - balloonAsset = (s8 *) get_misc_asset(ASSET_MISC_12); + balloonAsset = (s8 *) get_misc_asset(ASSET_MISC_BALLOON_DATA); angleVel = balloonAsset[(racer->balloon_type * 10) + (racer->balloon_level * 2)]; } @@ -3448,9 +3458,9 @@ void func_8005250C(Object *obj, Object_Racer *racer, s32 updateRate) { if (racer->unk1F3 & 8) { if (gNumViewports < 3) { if (gCurrentPlayerIndex >= PLAYER_ONE) { - obj->unk74 |= 0x100000; + obj->particleEmitFlags |= 0x100000; } else { - obj->unk74 |= 0x80000; + obj->particleEmitFlags |= 0x80000; } } racer->unk1F2 = 4; @@ -3610,13 +3620,13 @@ void racer_spinout_car(Object *obj, Object_Racer *racer, s32 updateRate, f32 upd angleVel = racer->y_rotation_vel; if (gCurrentPlayerIndex > PLAYER_COMPUTER) { if (gNumViewports < VIEWPORTS_COUNT_4_PLAYERS) { - obj->unk74 |= 0x4FC00; + obj->particleEmitFlags |= 0x4FC00; } else { if (racer->wheel_surfaces[2] < SURFACE_NONE) { - obj->unk74 |= 1 << (racer->wheel_surfaces[2] * 2); + obj->particleEmitFlags |= 1 << (racer->wheel_surfaces[2] * 2); } if (racer->wheel_surfaces[3] < SURFACE_NONE) { - obj->unk74 |= 2 << (racer->wheel_surfaces[3] * 2); + obj->particleEmitFlags |= 2 << (racer->wheel_surfaces[3] * 2); } } } @@ -3670,13 +3680,13 @@ void update_car_velocity_offground(Object *obj, Object_Racer *racer, s32 updateR racer->x_rotation_vel += (angle >> 3); //!@Delta } if (racer->unk18) { - func_8000488C((void *) racer->unk18); + sound_stop((void *) racer->unk18); } if (racer->unk10) { - func_8000488C((void *) racer->unk10); + sound_stop((void *) racer->unk10); } if (racer->unk14) { - func_8000488C((void *) racer->unk14); + sound_stop((void *) racer->unk14); } if (racer->unk1FE == 1 || racer->unk1FE == 3) { racer->unk1E8 = racer->steerAngle; @@ -3744,7 +3754,7 @@ void update_car_velocity_offground(Object *obj, Object_Racer *racer, s32 updateR canSteer = TRUE; } if (canSteer) { - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; racer->drift_direction = 0; racer->unk10C -= (racer->unk10C * updateRate) >> 4; gCurrentCarSteerVel = 0; @@ -3778,7 +3788,7 @@ void update_car_velocity_offground(Object *obj, Object_Racer *racer, s32 updateR } racer->trickType = steerAngle; } - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; } /** @@ -4047,7 +4057,7 @@ void update_onscreen_AI_racer(Object *obj, Object_Racer *racer, s32 updateRate, func_80054FD0(obj, racer, updateRate); } if (!racer->unk201) { - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; } else if (racer->vehicleID < VEHICLE_TRICKY) { func_800AF714(obj, updateRate); } @@ -4177,10 +4187,10 @@ void update_car_velocity_ground(Object *obj, Object_Racer *racer, s32 updateRate } if (get_viewport_count() < 2 && sp38 && racer->velocity < -2.0) { if (racer->wheel_surfaces[2] < SURFACE_NONE) { - obj->unk74 |= 1 << (racer->wheel_surfaces[2] * 2); + obj->particleEmitFlags |= 1 << (racer->wheel_surfaces[2] * 2); } if (racer->wheel_surfaces[3] < SURFACE_NONE) { - obj->unk74 |= 2 << (racer->wheel_surfaces[3] * 2); + obj->particleEmitFlags |= 2 << (racer->wheel_surfaces[3] * 2); } } vel = racer->velocity; @@ -4425,7 +4435,7 @@ void handle_racer_items(Object *obj, Object_Racer *racer, UNUSED s32 updateRate) play_char_horn_sound(obj, racer); } } else { - miscAsset = (s8 *) get_misc_asset(ASSET_MISC_12); + miscAsset = (s8 *) get_misc_asset(ASSET_MISC_BALLOON_DATA); weaponID = miscAsset[(racer->balloon_type * 10) + (racer->balloon_level * 2)]; if (miscAsset[(racer->balloon_type * 10) + (racer->balloon_level * 2)] == WEAPON_NONE) { racer->balloon_quantity = 0; @@ -4646,7 +4656,7 @@ void handle_racer_items(Object *obj, Object_Racer *racer, UNUSED s32 updateRate) NULL); } else { if (racer->weaponSoundMask) { - func_8000488C(racer->weaponSoundMask); + sound_stop(racer->weaponSoundMask); } sound_play_spatial(soundID, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, (s32 **) &racer->weaponSoundMask); @@ -4960,7 +4970,7 @@ void drop_bananas(Object *obj, Object_Racer *racer, s32 number) { if (bananaObj != NULL) { bananaObj->segment.level_entry = NULL; banana = (Object_Banana *) bananaObj->unk64; - banana->unk9 = racer->vehicleID; + banana->droppedVehicleID = racer->vehicleID; bananaObj->segment.x_velocity = racer->ox1 * 2; bananaObj->segment.y_velocity = (0.0f - racer->oy1) + 5.0; bananaObj->segment.z_velocity = racer->oz1 * 2; @@ -4973,7 +4983,7 @@ void drop_bananas(Object *obj, Object_Racer *racer, s32 number) { bananaObj->segment.y_velocity -= racer->oy3 * variance; bananaObj->segment.z_velocity -= (racer->oz3 - racer->oz1) * variance; } - bananaObj->properties.banana.unk0 = 1; + bananaObj->properties.banana.status = BANANA_DROPPED; } } number--; @@ -5397,7 +5407,7 @@ void update_camera_finish_race(UNUSED f32 updateRate, Object *obj, Object_Racer f32 distance; cameraID = racer->spectateCamID; - cam = find_nearest_spectate_camera(obj, &cameraID); + cam = spectate_nearest(obj, &cameraID); if (cam == NULL) { gCameraObject->mode = CAMERA_FINISH_CHALLENGE; return; @@ -5639,70 +5649,85 @@ void get_timestamp_from_frames(s32 frameCount, s32 *minutes, s32 *seconds, s32 * * The path node pool is globally loaded, despite only being used in time trial. */ void allocate_ghost_data(void) { - gGhostData[0] = allocate_from_main_pool_safe( - (sizeof(GhostNode) + sizeof(GhostDataFrame)) * MAX_NUMBER_OF_GHOST_NODES, COLOUR_TAG_RED); + // Allocate two sets of ghost data. One for the current playing ghost, and one for the new ghost being written. + gGhostData[0] = allocate_from_main_pool_safe((sizeof(GhostNode) * 2) * MAX_NUMBER_OF_GHOST_NODES, COLOUR_TAG_RED); gGhostData[1] = ((GhostNode *) gGhostData[0] + MAX_NUMBER_OF_GHOST_NODES); - gGhostData[2] = NULL; // T.T. Ghost - D_8011D5A0[0] = 0; - D_8011D5A0[1] = 0; - D_8011D5A0[2] = 0; - D_8011D5A8[0] = CONTPAK_ERROR_NONE; - D_8011D5A8[1] = CONTPAK_ERROR_NONE; - D_8011D59D = 0; - D_8011D5AC = -1; -} - -void func_80059944(void) { - D_8011D59C = D_8011D59D; - D_8011D5A0[D_8011D59C] = 0; - D_8011D5A8[D_8011D59C] = CONTPAK_ERROR_NONE; - D_8011D59E = 0; -} - -void func_80059984(s32 arg0) { - D_8011D59D = ((D_8011D59C + 1) & 1); - D_8011D5AC = arg0; -} -// get_previous_map_id? -s32 func_800599A8(void) { - return D_8011D5AC; -} - -s32 func_800599B8(s32 arg0, s32 mapId, s16 arg2, s16 *arg3, s16 *arg4) { - s32 temp_v0; - s32 temp_t8; - s16 sp2E; - - temp_t8 = (D_8011D59C + 1) & 1; - temp_v0 = func_80074B34(arg0, mapId, arg2, (u16 *) arg3, arg4, &sp2E, (GhostHeader *) gGhostData[temp_t8]); - if (arg3 != 0) { - if (temp_v0 == 0) { - D_8011D5A0[temp_t8] = sp2E; - D_8011D5AC = mapId; - } else { - D_8011D5AC = -1; - } - } - - return temp_v0; + gGhostData[GHOST_STAFF] = NULL; // T.T. Ghost + gGhostNodeCount[0] = 0; + gGhostNodeCount[1] = 0; + gGhostNodeCount[GHOST_STAFF] = 0; + gGhostNodeFull[0] = FALSE; + gGhostNodeFull[1] = FALSE; + gPrevGhostNodeIndex = 0; + gGhostMapID = -1; } /** - * Loads T.T. ghost node data into gGhostData[2]. + * Reset all the player ghost playback variables to default. + * Also set the ghost index. + */ +void timetrial_reset_player_ghost(void) { + gCurrentGhostIndex = gPrevGhostNodeIndex; + gGhostNodeCount[gCurrentGhostIndex] = 0; + gGhostNodeFull[gCurrentGhostIndex] = FALSE; + gGhostNodeDelay = 0; +} + +/** + * Swap player ghost index and set the new saved map ID. + */ +void timetrial_swap_player_ghost(s32 mapID) { + gPrevGhostNodeIndex = (gCurrentGhostIndex + 1) & 1; + gGhostMapID = mapID; +} + +/** + * Return the current map ID associated with the time trial ghost. + */ +s32 timetrial_map_id(void) { + return gGhostMapID; +} + +/** + * Attempt to load the player ghost data from the controller pak. + * Returns the controller pak status when done. + */ +s32 timetrial_load_player_ghost(s32 controllerID, s32 mapId, s16 arg2, s16 *characterID, s16 *time) { + s32 cpakStatus; + s32 nodeID; + s16 nodeCount; + + nodeID = (gCurrentGhostIndex + 1) & 1; + cpakStatus = func_80074B34(controllerID, mapId, arg2, (u16 *) characterID, time, &nodeCount, + (GhostHeader *) gGhostData[nodeID]); + if (characterID) { + if (cpakStatus == CONTROLLER_PAK_GOOD) { + gGhostNodeCount[nodeID] = nodeCount; + gGhostMapID = mapId; + } else { + gGhostMapID = -1; + } + } + + return cpakStatus; +} + +/** + * Loads T.T. ghost node data into gGhostData[GHOST_STAFF]. * Returns 0 if successful, or 1 if an error occured. */ s32 load_tt_ghost(s32 ghostOffset, s32 size, s16 *outTime) { GhostHeader *ghost = allocate_from_main_pool_safe(size, COLOUR_TAG_RED); if (ghost != NULL) { load_asset_to_address(ASSET_TTGHOSTS, (u32) ghost, ghostOffset, size); - if (gGhostData[2] != NULL) { - free_from_memory_pool(gGhostData[2]); + if (gGhostData[GHOST_STAFF] != NULL) { + free_from_memory_pool(gGhostData[GHOST_STAFF]); } - gGhostData[2] = allocate_from_main_pool_safe(size - sizeof(GhostHeader), COLOUR_TAG_WHITE); - if (gGhostData[2] != NULL) { + gGhostData[GHOST_STAFF] = allocate_from_main_pool_safe(size - sizeof(GhostHeader), COLOUR_TAG_WHITE); + if (gGhostData[GHOST_STAFF] != NULL) { *outTime = ghost->time; - D_8011D5A0[2] = ghost->nodeCount; - bcopy((u8 *) ghost + 8, gGhostData[2], size - sizeof(GhostHeader)); + gGhostNodeCount[GHOST_STAFF] = ghost->nodeCount; + bcopy((u8 *) ghost + 8, gGhostData[GHOST_STAFF], size - sizeof(GhostHeader)); free_from_memory_pool(ghost); return 0; } @@ -5711,19 +5736,30 @@ s32 load_tt_ghost(s32 ghostOffset, s32 size, s16 *outTime) { return 1; } -void free_tt_ghost_data(void) { - if (gGhostData[2] != NULL) { - free_from_memory_pool(gGhostData[2]); +/** + * Free the staff ghost from memory if it exists. + */ +void timetrial_free_staff_ghost(void) { + if (gGhostData[GHOST_STAFF] != NULL) { + free_from_memory_pool(gGhostData[GHOST_STAFF]); } - gGhostData[2] = NULL; + gGhostData[GHOST_STAFF] = NULL; } -SIDeviceStatus func_80059B7C(s32 controllerIndex, s32 mapId, s16 arg2, s16 arg3, s16 arg4) { - return func_80075000(controllerIndex, (s16) mapId, arg2, arg3, arg4, D_8011D5A0[D_8011D59C], - (GhostHeader *) gGhostData[D_8011D59C]); +/** + * Calls a function that attempts to write the player ghost data to the controller pak. + * Returns the controller pak status when finished. + */ +SIDeviceStatus timetrial_write_player_ghost(s32 controllerIndex, s32 mapId, s16 arg2, s16 arg3, s16 arg4) { + return func_80075000(controllerIndex, (s16) mapId, arg2, arg3, arg4, gGhostNodeCount[gCurrentGhostIndex], + (GhostHeader *) gGhostData[gCurrentGhostIndex]); } -void func_80059BF0(Object *obj, s32 updateRate) { +/** + * Write down the current position and rotation every half second to the ghost node data. + * Returns early if the ghost node data is full. + */ +void timetrial_ghost_write(Object *obj, s32 updateRate) { f32 yOffset; Object_Racer *racer; GhostNode *ghostNode; @@ -5734,34 +5770,38 @@ void func_80059BF0(Object *obj, s32 updateRate) { yOffset *= 0.5; } yOffset = 17.0f - (yOffset * 17.0f); - D_8011D59E -= updateRate; - if (D_8011D59E > 0) { + gGhostNodeDelay -= updateRate; + if (gGhostNodeDelay > 0) { return; } - while (D_8011D59E <= 0) { - D_8011D59E += 30; - if (D_8011D5A0[D_8011D59C] >= 360) { + while (gGhostNodeDelay <= 0) { + gGhostNodeDelay += 30; + if (gGhostNodeCount[gCurrentGhostIndex] >= 360) { if (!is_postrace_viewport_active()) { - D_8011D5A8[D_8011D59C] = CONTPAK_ERROR_UNKNOWN; + gGhostNodeFull[gCurrentGhostIndex] = TRUE; } return; } - ghostNode = gGhostData[D_8011D59C] + D_8011D5A0[D_8011D59C]; + ghostNode = gGhostData[gCurrentGhostIndex] + gGhostNodeCount[gCurrentGhostIndex]; ghostNode->x = obj->segment.trans.x_position; ghostNode->y = obj->segment.trans.y_position + yOffset; ghostNode->z = obj->segment.trans.z_position; ghostNode->yRotation = obj->segment.trans.y_rotation + racer->y_rotation_offset; ghostNode->xRotation = obj->segment.trans.x_rotation + racer->x_rotation_offset; ghostNode->zRotation = obj->segment.trans.z_rotation + racer->z_rotation_offset; - D_8011D5A0[D_8011D59C]++; + gGhostNodeCount[gCurrentGhostIndex]++; } } -s16 func_80059E20(void) { - return D_8011D5A8[D_8011D59C]; +/** + * Returns true if the time trial ghost has reached its size limit. + */ +s16 timetrial_ghost_full(void) { + return gGhostNodeFull[gCurrentGhostIndex]; } #ifdef NON_EQUIVALENT +// timetrial_ghost_read s32 set_ghost_position_and_rotation(Object *obj) { f32 vectorX[3]; f32 vectorY[3]; @@ -5780,8 +5820,8 @@ s32 set_ghost_position_and_rotation(Object *obj) { s32 rot; s32 i; - ghostDataIndex = (D_8011D59C + 1) & 1; - if (is_time_trial_ghost(obj)) { + ghostDataIndex = (gCurrentGhostIndex + 1) & 1; + if (timetrial_staff_ghost_check(obj)) { ghostDataIndex = 2; } @@ -5791,11 +5831,11 @@ s32 set_ghost_position_and_rotation(Object *obj) { } commonUnk0s32 = commonUnk0f32; // Truncate the float to an integer? - ghostNodeCount = D_8011D5A0[ghostDataIndex]; + ghostNodeCount = gGhostNodeCount[ghostDataIndex]; if (commonUnk0s32 >= (ghostNodeCount - 2)) { return FALSE; } - if (ghostDataIndex != 2 && get_current_map_id() != D_8011D5AC) { + if (ghostDataIndex != 2 && get_current_map_id() != gGhostMapID) { return FALSE; } ghostData = gGhostData[ghostDataIndex]; @@ -5864,7 +5904,7 @@ s32 set_ghost_position_and_rotation(Object *obj) { } obj->segment.trans.z_rotation = rot + (s32) (rotDiff * catmullX); - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; obj->segment.object.segmentID = get_level_segment_index_from_position( obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position); if (ghostNodeCount == (commonUnk0s32 + 3)) { @@ -5897,6 +5937,7 @@ void racer_set_dialogue_camera(void) { gRacerDialogueCamera = TRUE; } +#ifdef ANTI_TAMPER /** * Antipiracy function that loops over an address of a function a number of times. * It compares the number it gets to a generated checksum to determine if the game has been tampered with at all. @@ -5914,6 +5955,7 @@ void compare_balloon_checksums(void) { gAntiPiracyHeadroll = 0x800; } } +#endif /** * When you enter a door, take control away from the player. @@ -6204,7 +6246,7 @@ void update_AI_racer(Object *obj, Object_Racer *racer, s32 updateRate, f32 updat } if (racer->magnetTimer == 0) { if (racer->magnetSoundMask != NULL) { - func_8000488C(racer->magnetSoundMask); + sound_stop(racer->magnetSoundMask); racer->magnetSoundMask = NULL; } } @@ -6232,11 +6274,15 @@ void update_AI_racer(Object *obj, Object_Racer *racer, s32 updateRate, f32 updat } var_t2 = ((racer->headAngleTarget - racer->headAngle) * updateRate) >> 3; CLAMP(var_t2, -0x800, 0x800) +#ifdef ANTI_TAMPER if (gAntiPiracyHeadroll) { racer->headAngle += gAntiPiracyHeadroll; } else { racer->headAngle += var_t2; } +#else + racer->headAngle += var_t2; +#endif if (racer->shieldTimer > 0) { if (racer->shieldTimer > 60) { if (racer->shieldSoundMask) { @@ -6520,7 +6566,7 @@ void func_8005B818(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR racer->unkFC.x = obj->segment.trans.x_position; racer->unkFC.y = obj->segment.trans.y_position; racer->unkFC.z = obj->segment.trans.z_position; - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; func_800AF714(obj, updateRate); } } @@ -6528,6 +6574,7 @@ void func_8005B818(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR GLOBAL_ASM("asm/non_matchings/racer/func_8005B818.s") #endif +#ifdef ANTI_TAMPER // This gets called if an anti-piracy checksum fails in allocate_object_model_pools. /** * Triggered upon failure of an anti-tamper test. Sets the first index of the surface speed @@ -6536,6 +6583,7 @@ GLOBAL_ASM("asm/non_matchings/racer/func_8005B818.s") void antipiracy_modify_surface_traction_table(void) { gSurfaceTractionTable[SURFACE_DEFAULT] = 0.05f; } +#endif void func_8005C270(Object_Racer *racer) { s32 temp = get_checkpoint_count(); diff --git a/src/racer.h b/src/racer.h index 0af0e393..4dcbbfee 100644 --- a/src/racer.h +++ b/src/racer.h @@ -7,6 +7,7 @@ #include "save_data.h" #define SEGMENT_NONE -1 // If the level in question does not use segmentation. +#define GHOST_STAFF 2 typedef enum ActivePlayers { PLAYER_COMPUTER = -1, @@ -31,6 +32,13 @@ typedef enum BoostSound { BOOST_SOUND_UNK4 } BoostSound; +typedef enum ObjectElevation { + ELEVATION_LOW, + ELEVATION_NORMAL, + ELEVATION_HIGH, + ELEVATION_HIGHEST +} ObjectElevation; + // boost types suffixed with _FAST are the ones you get from releasing the throttle. typedef enum BoostType { BOOST_SMALL, @@ -175,14 +183,14 @@ void handle_base_steering(Object_Racer *racer, s32 updateRate, f32 updateRateF); void second_racer_camera_update(Object *obj, Object_Racer *racer, s32 mode, f32 updateRateF); void get_timestamp_from_frames(s32 frameCount, s32 *minutes, s32 *seconds, s32 *hundredths); void allocate_ghost_data(void); -void func_80059944(void); -void func_80059984(s32 arg0); -s32 func_800599A8(void); -s32 func_800599B8(s32 arg0, s32 mapId, s16 arg2, s16 *arg3, s16 *arg4); +void timetrial_reset_player_ghost(void); +void timetrial_swap_player_ghost(s32 mapID); +s32 timetrial_map_id(void); +s32 timetrial_load_player_ghost(s32 controllerID, s32 mapId, s16 arg2, s16 *characterID, s16 *time); s32 load_tt_ghost(s32 ghostOffset, s32 size, s16 *outTime); -void free_tt_ghost_data(void); -SIDeviceStatus func_80059B7C(s32 controllerIndex, s32 mapId, s16 arg2, s16 arg3, s16 arg4); -s16 func_80059E20(void); +void timetrial_free_staff_ghost(void); +SIDeviceStatus timetrial_write_player_ghost(s32 controllerIndex, s32 mapId, s16 arg2, s16 arg3, s16 arg4); +s16 timetrial_ghost_full(void); void disable_racer_input(void); void racer_set_dialogue_camera(void); void compare_balloon_checksums(void); @@ -222,7 +230,7 @@ void handle_racer_items(Object *obj, Object_Racer *racer, s32 updateRate); void drop_bananas(Object *obj, Object_Racer *racer, s32 number); void update_player_racer(Object *obj, s32 updateRate); void func_80045128(Object **racerObjs); -void func_80059BF0(Object *obj, s32 updateRate); +void timetrial_ghost_write(Object *obj, s32 updateRate); //Non Matching s32 set_ghost_position_and_rotation(Object *obj); diff --git a/src/save_data.c b/src/save_data.c index 6cb8677f..f845a2e4 100644 --- a/src/save_data.c +++ b/src/save_data.c @@ -1162,7 +1162,7 @@ s16 calculate_ghost_header_checksum(GhostHeader *ghostHeader) { s16 sum; sum = 0; - len = (s16) (ghostHeader->nodeCount * sizeof(GhostDataFrame)) + sizeof(GhostHeader); + len = (s16) (ghostHeader->nodeCount * sizeof(GhostNode)) + sizeof(GhostHeader); for (i = 2; i < len; i++) { sum += ((u8 *) ghostHeader)[i]; } @@ -1175,7 +1175,7 @@ void func_80074AA8(GhostHeader *ghostHeader, s16 characterID, s16 time, s16 node ghostHeader->unk3 = 0; ghostHeader->time = time; ghostHeader->nodeCount = nodeCount; - bcopy(dest, (u8 *) ghostHeader + 8, nodeCount * sizeof(GhostDataFrame)); + bcopy(dest, (u8 *) ghostHeader + 8, nodeCount * sizeof(GhostNode)); ghostHeader->checksum = calculate_ghost_header_checksum(ghostHeader); } @@ -1199,6 +1199,7 @@ typedef struct unkGhostData { u8 unkB; u8 unkC; } unkGhostData; +// cpak_read_ghost s32 func_80074B34(s32 controllerIndex, s16 levelId, s16 vehicleId, u16 *ghostCharacterId, s16 *ghostTime, s16 *ghostNodeCount, GhostHeader *ghostData) { #define GHSS_FILE_SIZE 0x100 diff --git a/src/thread3_main.c b/src/thread3_main.c index 18656240..1dfc3d03 100644 --- a/src/thread3_main.c +++ b/src/thread3_main.c @@ -173,10 +173,12 @@ void init_game(void) { stubbed_printf(sDebugRomBuildInfo); init_main_memory_pool(); init_rzip(); // Initialise gzip decompression related things +#ifdef ANTI_TAMPER sAntiPiracyTriggered = TRUE; if (check_imem_validity()) { sAntiPiracyTriggered = FALSE; } +#endif gIsLoading = FALSE; gLevelDefaultVehicleID = VEHICLE_CAR; @@ -189,11 +191,13 @@ void init_game(void) { } osCreateScheduler(&gMainSched, &gSchedStack[0x400], /*priority*/ 13, viMode, 1); +#ifdef ANTI_TAMPER // Antipiracy measure. gDmemInvalid = FALSE; if (check_dmem_validity() == FALSE) { gDmemInvalid = TRUE; } +#endif init_video(VIDEO_MODE_LOWRES_LPN, &gMainSched); init_PI_mesg_queue(); setup_gfx_mesg_queues(&gMainSched); @@ -373,7 +377,7 @@ void load_level_game(s32 levelId, s32 numberOfPlayers, s32 entranceId, Vehicle v load_level(levelId, numberOfPlayers, entranceId, vehicleId, gGameCurrentCutscene); init_hud(get_viewport_count()); func_800AE728(8, 0x10, 0x96, 0x64, 0x32, 0); - func_8001BF20(); + ainode_update(); osSetTime(0); set_free_queue_state(2); rumble_init(TRUE); @@ -419,10 +423,12 @@ void ingame_logic_loop(s32 updateRate) { buttonHeldInputs |= get_buttons_held_from_player(i); buttonPressedInputs |= get_buttons_pressed_from_player(i); } +#ifdef ANTI_TAMPER // Spam the start button, making the game unplayable because it's constantly paused. if (sAntiPiracyTriggered) { buttonPressedInputs |= START_BUTTON; } +#endif // Update all objects if (!gIsPaused) { func_80010994(updateRate); @@ -446,7 +452,7 @@ void ingame_logic_loop(s32 updateRate) { gIsPaused = FALSE; } gParticlePtrList_flush(); - func_8001BF20(); + ainode_update(); render_scene(&gCurrDisplayList, &gGameCurrMatrix, &gGameCurrVertexList, &gGameCurrTriList, updateRate); if (gGameMode == GAMEMODE_INGAME) { // Ignore the user's L/R/Z buttons. @@ -491,12 +497,12 @@ void ingame_logic_loop(s32 updateRate) { } } process_onscreen_textbox(updateRate); - i = func_800C3400(); + i = textbox_visible(); if (i != 0) { if (i == 2) { gIsPaused = TRUE; } - if (func_800C3400() != 2) { + if (textbox_visible() != 2) { gIsPaused = FALSE; n_alSeqpDelete(); } @@ -537,7 +543,7 @@ void ingame_logic_loop(s32 updateRate) { gIsPaused = FALSE; break; case 6: - func_80022E18(1); + mode_end_taj_race(CHALLENGE_END_QUIT); gIsPaused = FALSE; break; case 3: @@ -550,9 +556,9 @@ void ingame_logic_loop(s32 updateRate) { } } init_rdp_and_framebuffer(&gCurrDisplayList); - render_borders_for_multiplayer(&gCurrDisplayList); + divider_draw(&gCurrDisplayList); render_minimap_and_misc_hud(&gCurrDisplayList, &gGameCurrMatrix, &gGameCurrVertexList, updateRate); - render_second_multiplayer_borders(&gCurrDisplayList); + divider_clear_coverage(&gCurrDisplayList); if (gFutureFunLandLevelTarget) { if (func_800214C4() != 0) { gPlayableMapId = ASSET_LEVEL_FUTUREFUNLANDHUB; @@ -858,7 +864,7 @@ void load_level_menu(s32 levelId, s32 numberOfPlayers, s32 entranceId, Vehicle v load_level(levelId, numberOfPlayers, entranceId, vehicleId, cutsceneId); init_hud(get_viewport_count()); func_800AE728(4, 4, 0x6E, 0x30, 0x20, 0); - func_8001BF20(); + ainode_update(); osSetTime(0); set_free_queue_state(2); } @@ -889,12 +895,12 @@ void update_menu_scene(s32 updateRate) { if (get_thread30_level_id_to_load() == NULL) { func_80010994(updateRate); gParticlePtrList_flush(); - func_8001BF20(); + ainode_update(); render_scene(&gCurrDisplayList, &gGameCurrMatrix, &gGameCurrVertexList, &gGameCurrTriList, updateRate); process_onscreen_textbox(updateRate); init_rdp_and_framebuffer(&gCurrDisplayList); - render_borders_for_multiplayer(&gCurrDisplayList); - render_second_multiplayer_borders(&gCurrDisplayList); + divider_draw(&gCurrDisplayList); + divider_clear_coverage(&gCurrDisplayList); } } @@ -1573,6 +1579,7 @@ s32 is_controller_missing(void) { } } +#ifdef ANTI_TAMPER /** * Ran on boot, will make sure the CIC chip (CIC6103) is to spec. Will return true if it's all good, otherwise it * returns false. The intention of this function, is an attempt to check that the cartridge is a legitimate copy. A @@ -1585,3 +1592,4 @@ s32 check_imem_validity(void) { } return TRUE; } +#endif diff --git a/src/tracks.c b/src/tracks.c index 6435177f..6d93b242 100644 --- a/src/tracks.c +++ b/src/tracks.c @@ -69,9 +69,8 @@ ObjectSegment *gSceneActiveCamera; s32 gSceneCurrentPlayerID; Object *gSkydomeSegment; -UNUSED s32 - gIsNearCurrBBox; // Set to true if the current visible segment is close to the camera. Never actually used though. -UNUSED s32 D_8011B0C0; // Set to 0 then never read. +UNUSED s32 gIsNearCurrBBox; // Set to true if the current visible segment is close to the camera. +UNUSED s32 D_8011B0C0; // Set to 0 then never read. UNUSED s32 gDisableShadows; // Never not 0. s32 gShadowHeapFlip; // Flips between 0 and 1 to prevent incorrect access between frames. s32 D_8011B0CC; @@ -235,7 +234,7 @@ void init_track(u32 geometry, u32 skybox, s32 numberOfPlayers, Vehicle vehicle, spawn_skydome(skybox); D_8011B110 = 0; D_8011B114 = 0x10000; - func_80011390(); + path_enable(); func_8000C8F8(arg6, 0); func_8000C8F8(collectables, 1); gScenePlayerViewports = numberOfPlayers; @@ -333,10 +332,12 @@ void render_scene(Gfx **dList, MatrixS **mtx, Vertex **vtx, TriangleList **tris, if (get_filtered_cheats() & CHEAT_MIRRORED_TRACKS) { flip = TRUE; } +#ifdef ANTI_TAMPER // Antipiracy measure if (IO_READ(0x200) != 0xAC290000) { flip = TRUE; } +#endif reset_render_settings(&gSceneCurrDisplayList); gDkrDisableBillboard(gSceneCurrDisplayList++); gSPClearGeometryMode(gSceneCurrDisplayList++, G_CULL_FRONT); @@ -386,7 +387,7 @@ void render_scene(Gfx **dList, MatrixS **mtx, Vertex **vtx, TriangleList **tris, process_weather(&gSceneCurrDisplayList, &gSceneCurrMatrix, &gSceneCurrVertexList, &gSceneCurrTriList, tempUpdateRate); } - func_800AD030(get_active_camera_segment()); + lensflare_override(get_active_camera_segment()); func_800ACA20(&gSceneCurrDisplayList, &gSceneCurrMatrix, &gSceneCurrVertexList, get_active_camera_segment()); render_hud(&gSceneCurrDisplayList, &gSceneCurrMatrix, &gSceneCurrVertexList, get_racer_object_by_port(gSceneCurrentPlayerID), updateRate); @@ -413,7 +414,7 @@ void render_scene(Gfx **dList, MatrixS **mtx, Vertex **vtx, TriangleList **tris, gDPPipeSync(gSceneCurrDisplayList++); initialise_player_viewport_vars(updateRate); set_weather_limits(-1, -512); - func_800AD030(get_active_camera_segment()); + lensflare_override(get_active_camera_segment()); func_800ACA20(&gSceneCurrDisplayList, &gSceneCurrMatrix, &gSceneCurrVertexList, get_active_camera_segment()); set_text_font(FONT_COLOURFUL); @@ -706,8 +707,10 @@ void animate_level_textures(s32 updateRate) { void spawn_skydome(s32 objectID) { LevelObjectEntryCommon spawnObject; +#ifdef ANTI_TAMPER // Antipiracy measure compare_balloon_checksums(); +#endif if (objectID == -1) { gSkydomeSegment = NULL; return; @@ -1553,7 +1556,7 @@ s32 check_if_in_draw_range(Object *obj) { obj64 = obj->unk64; obj->segment.object.opacity = ((obj64->racer.transparency + 1) * alpha) >> 8; break; - case BHV_UNK_3A: // Ghost Object? + case BHV_TIMETRIAL_GHOST: // Ghost Object? obj64 = obj->unk64; obj->segment.object.opacity = obj64->racer.transparency; break; diff --git a/src/vehicle_bluey.c b/src/vehicle_bluey.c index f84553ea..6bc0618c 100644 --- a/src/vehicle_bluey.c +++ b/src/vehicle_bluey.c @@ -171,12 +171,12 @@ void update_bluey(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *ra } animFrame = obj->segment.animFrame; obj->segment.animFrame = racer->animationSpeed; - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; if (obj->segment.object.animationID == ANIM_BLUEY_RUN) { play_footstep_sounds(obj, 2, animFrame, SOUND_STOMP2, SOUND_STOMP3); - obj->unk74 |= 3; + obj->particleEmitFlags |= OBJ_EMIT_PARTICLE_1 | OBJ_EMIT_PARTICLE_2; } - func_800AFC3C(obj, updateRate); + obj_spawn_particle(obj, updateRate); fade_when_near_camera(obj, racer, 40); firstRacerObj = get_racer_object(PLAYER_ONE); diffX = firstRacerObj->segment.trans.x_position - obj->segment.trans.x_position; diff --git a/src/vehicle_bubbler.c b/src/vehicle_bubbler.c index e117808a..fcf66ce5 100644 --- a/src/vehicle_bubbler.c +++ b/src/vehicle_bubbler.c @@ -142,8 +142,8 @@ void update_bubbler(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer * spawn_boss_hazard(obj, racer, 0.0f, objectID, SOUND_VOICE_BUBBLER_HOHO2); } } - obj->unk74 = 0; - func_800AFC3C(obj, updateRate); + obj->particleEmitFlags = OBJ_EMIT_OFF; + obj_spawn_particle(obj, updateRate); fade_when_near_camera(obj, racer, 40); switch (obj->segment.object.animationID) { case ANIM_BUBBLER_MOVE: diff --git a/src/vehicle_rocket.c b/src/vehicle_rocket.c index 91dcbdef..45c3cada 100644 --- a/src/vehicle_rocket.c +++ b/src/vehicle_rocket.c @@ -88,7 +88,7 @@ void update_rocket(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r func_80049794(updateRate, updateRateF, obj, racer); racer->vehicleID = racer->vehicleIDPrev; *startTimer = tempStartTimer; - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; racer->headAngle = tempHeadAngle; obj->segment.object.animationID = animID; obj->segment.animFrame = animFrame; @@ -131,7 +131,7 @@ void update_rocket(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r racer->animationSpeed = 0.0f; } obj->segment.animFrame = racer->animationSpeed; - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; func_800AF714(obj, updateRate); fade_when_near_camera(obj, racer, 40); if (*startTimer != 100) { diff --git a/src/vehicle_smokey.c b/src/vehicle_smokey.c index 33c971a3..66edf0f2 100644 --- a/src/vehicle_smokey.c +++ b/src/vehicle_smokey.c @@ -103,7 +103,7 @@ void update_smokey(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r func_80049794(updateRate, updateRateF, obj, racer); racer->vehicleID = racer->vehicleIDPrev; *startTimer = headAngleRange; - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; racer->headAngle = tempHeadAngle; obj->segment.object.animationID = animID; obj->segment.animFrame = animFrame; @@ -222,7 +222,7 @@ void update_smokey(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r animFrame = obj->segment.animFrame; obj->segment.animFrame = racer->animationSpeed; stepFrame = obj->segment.animFrame >> 4; - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; if (obj->segment.object.animationID != ANIM_SMOKEY_RUN && obj->segment.object.animationID != 2) { animFrame >>= 4; stepFrame = 1; @@ -237,7 +237,7 @@ void update_smokey(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r if (racer->vehicleIDPrev == VEHICLE_SMOKEY && racer->playerIndex == PLAYER_COMPUTER && func_80023568()) { spawn_boss_hazard(obj, racer, 100.0f, ASSET_OBJECT_ID_FIREBALL, SOUND_VOICE_TRICKY_HM); } - func_800AFC3C(obj, updateRate); + obj_spawn_particle(obj, updateRate); fade_when_near_camera(obj, racer, 40); firstRacerObj = get_racer_object(PLAYER_ONE); diffX = firstRacerObj->segment.trans.x_position - obj->segment.trans.x_position; diff --git a/src/vehicle_tricky.c b/src/vehicle_tricky.c index 4e014f4e..08c0066e 100644 --- a/src/vehicle_tricky.c +++ b/src/vehicle_tricky.c @@ -163,12 +163,12 @@ void update_tricky(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r } animFrame = obj->segment.animFrame; obj->segment.animFrame = racer->animationSpeed; - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; if (obj->segment.object.animationID == ANIM_TRICKY_RUN) { play_footstep_sounds(obj, 2, animFrame, SOUND_STOMP2, SOUND_STOMP3); - obj->unk74 |= 3; + obj->particleEmitFlags |= OBJ_EMIT_PARTICLE_1 | OBJ_EMIT_PARTICLE_2; } - func_800AFC3C(obj, updateRate); + obj_spawn_particle(obj, updateRate); fade_when_near_camera(obj, racer, 120); switch (obj->segment.object.animationID) { case ANIM_TRICKY_RUN: diff --git a/src/vehicle_wizpig.c b/src/vehicle_wizpig.c index de801e9c..9296347f 100644 --- a/src/vehicle_wizpig.c +++ b/src/vehicle_wizpig.c @@ -94,7 +94,7 @@ void update_wizpig(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r func_80049794(updateRate, updateRateF, obj, racer); racer->vehicleID = racer->vehicleIDPrev; *startTimer = tempStartTimer; - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; racer->headAngle = tempHeadAngle; obj->segment.object.animationID = animID; obj->segment.animFrame = animFrame; @@ -221,7 +221,7 @@ void update_wizpig(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r } animFrame = obj->segment.animFrame; obj->segment.animFrame = racer->animationSpeed; - obj->unk74 = 0; + obj->particleEmitFlags = OBJ_EMIT_OFF; if (obj->segment.object.animationID == ANIM_WIZPIG_RUN) { play_footstep_sounds(obj, 2, animFrame, SOUND_STOMP2, SOUND_STOMP3); } @@ -230,7 +230,7 @@ void update_wizpig(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r spawn_boss_hazard(obj, racer, 100.0f, ASSET_OBJECT_ID_FIREBALL, SOUND_VOICE_TRICKY_HM); } } - func_800AFC3C(obj, updateRate); + obj_spawn_particle(obj, updateRate); fade_when_near_camera(obj, racer, 40); firstRacerObj = get_racer_object(PLAYER_ONE); racer = (Object_Racer *) firstRacerObj->unk64; diff --git a/src/weather.c b/src/weather.c index 30bdf5c0..56231298 100644 --- a/src/weather.c +++ b/src/weather.c @@ -14,11 +14,7 @@ #include "math_util.h" #include "objects.h" -/************ .rodata ************/ - -const char D_800E87F0[] = "\nMaximum limit of %d lens flare switches, per level, has been exceeded."; - -/*********************************/ +#define WEATHER_OVERRIDE_COUNT 16 /************ .data ************/ @@ -43,7 +39,7 @@ Vertex *D_800E2914[2] = { NULL, NULL }; s32 *gWeatherAssetTable = NULL; // List of Ids s32 gWeatherAssetTableLength = 0; // Set, but never read. -Gfx D_800E2928[] = { +Gfx dLensFlare[] = { gsDPPipeSync(), gsDPSetCycleType(G_CYC_1CYCLE), gsDPSetTextureLOD(G_TL_TILE), @@ -57,37 +53,28 @@ Gfx D_800E2928[] = { gsSPEndDisplayList(), }; -unk800E2980 D_800E2980[2] = { - { 1, 0xFFFF, 0xC090, 3.0f, 0.0f }, - { 0, 0, 0, 0.0f, 0.0f }, -}; +LensFlareData gLensPresetLarge[2] = { { 1, { { { 255, 255, 192, 144 } } }, 3.0f, 0.0f }, { NULL } }; -unk800E2980 D_800E29A0[4] = { - { 3, 0xFFFF, 0x0090, 0.75f, -32.0f }, - { 2, 0x0050, 0xFF60, 0.8f, -96.0f }, - { 2, 0x00FF, 0x0090, 0.75f, -192.0f }, - { 0, 0, 0, 0.0f, 0.0f }, -}; +LensFlareData gLensPreset1[4] = { { 3, { { { 255, 255, 0, 144 } } }, 0.75f, -32.0f }, + { 2, { { { 0, 80, 255, 96 } } }, 0.8f, -96.0f }, + { 2, { { { 0, 255, 0, 144 } } }, 0.75f, -192.0f }, + { NULL } }; -unk800E2980 D_800E29E0[5] = { - { 3, 0xFF80, 0x1490, 0.65f, -64.0f }, - { 2, 0xFFFF, 0xFF90, 1.0f, -128.0f }, - { 3, 0xFFFF, 0x8090, 0.5f, -176.0f }, - { 3, 0xFF28, 0x2890, 0.75f, -224.0f }, - { 0, 0, 0, 0.0f, 0.0f }, -}; +LensFlareData gLensPreset2[5] = { { 3, { { { 255, 128, 20, 144 } } }, 0.65f, -64.0f }, + { 2, { { { 255, 255, 255, 144 } } }, 1.0f, -128.0f }, + { 3, { { { 255, 255, 128, 144 } } }, 0.5f, -176.0f }, + { 3, { { { 255, 40, 40, 144 } } }, 0.75f, -224.0f }, + { NULL } }; -unk800E2980 D_800E2A30[5] = { - { 3, 0xFF80, 0xFF80, 0.5f, -64.0f }, - { 1, 0xFFFF, 0xC090, 0.75f, -128.0f }, - { 2, 0xFF28, 0x0080, 0.6f, -176.0f }, - { 1, 0xFFC0, 0xFF90, 0.75f, -224.0f }, - { 0, 0, 0, 0.0f, 0.0f }, -}; +LensFlareData gLensPreset3[5] = { { 3, { { { 255, 128, 255, 128 } } }, 0.5f, -64.0f }, + { 1, { { { 255, 255, 192, 144 } } }, 0.75f, -128.0f }, + { 2, { { { 255, 40, 0, 128 } } }, 0.6f, -176.0f }, + { 1, { { { 255, 192, 255, 144 } } }, 0.75f, -224.0f }, + { NULL } }; -Object *D_800E2A80 = NULL; -s32 D_800E2A84 = TRUE; -s32 D_800E2A88 = 0; +Object *gLensFlare = NULL; +s32 gLensFlareOff = TRUE; +s32 gLensFlareOverrideObjs = 0; f32 D_800E2A8C = -200.0f; f32 D_800E2A90 = 200.0f; f32 D_800E2A94 = 200.0f; @@ -153,11 +140,11 @@ Vertex *gCurrWeatherVertexList; TriangleList *gCurrWeatherTriList; ObjectSegment *gWeatherCamera; Matrix *gWeatherCameraMatrix; -s32 D_80127C24; -s32 D_80127C28; -Matrix *D_80127C2C; -Vec3f D_80127C30; -Object *D_80127C40[16]; +LensFlareData *gLensFlareSet1; +LensFlareData *gLensFlareSet2; +LensFlareData *gLensFlareLarge; +Vec3f gLensFlarePos; +Object *gLensFlareSwitches[WEATHER_OVERRIDE_COUNT]; /******************************/ @@ -177,9 +164,9 @@ void init_weather(void) { D_800E290C = 0; D_80127BF8.unk0 = -1; D_80127BF8.unk2 = -512; - D_800E2A80 = NULL; - D_800E2A84 = TRUE; - D_800E2A88 = 0; + gLensFlare = NULL; + gLensFlareOff = TRUE; + gLensFlareOverrideObjs = 0; if (gWeatherAssetTable == NULL) { gWeatherAssetTable = (s32 *) load_asset_section_from_rom(ASSET_WEATHER_PARTICLES); gWeatherAssetTableLength = 0; @@ -233,9 +220,9 @@ void free_weather_memory(void) { FREE_TEX(D_800E28D8.unk8); FREE_MEM(D_800E2910); - D_800E2A88 = 0; - D_800E2A80 = NULL; - D_800E2A84 = TRUE; + gLensFlareOverrideObjs = 0; + gLensFlare = NULL; + gLensFlareOff = TRUE; if (gWeatherType != WEATHER_SNOW) { free_rain_memory(); } @@ -284,7 +271,6 @@ void changeWeather(s32 arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5) { func_800AD2C4(arg3 + 1, arg4 + 1, (f32) arg5 / 60.0f); } } - /** * The root function for handling all weather. * Decide whether to perform rain or snow logic, execute it, then set it to render right after. @@ -407,6 +393,7 @@ GLOBAL_ASM("asm/non_matchings/weather/func_800AC21C.s") void render_falling_snow(void) { s32 i; u32 mtx; + u32 vtx; if (D_800E28D8.unk8 != NULL) { D_80127C00 = 4; @@ -418,136 +405,168 @@ void render_falling_snow(void) { gDkrInsertMatrix(gCurrWeatherDisplayList++, G_MTX_DKR_INDEX_0, 0); load_and_set_texture_no_offset(&gCurrWeatherDisplayList, D_800E28D8.unk8, RENDER_Z_COMPARE); while (i + D_80127C00 < D_800E2908) { - mtx = (u32) &D_800E2904[i]; - gSPVertexDKR(gCurrWeatherDisplayList++, OS_PHYSICAL_TO_K0(mtx), D_80127C00, 0); + vtx = (u32) &D_800E2904[i]; + gSPVertexDKR(gCurrWeatherDisplayList++, OS_PHYSICAL_TO_K0(vtx), D_80127C00, 0); gSPPolygon(gCurrWeatherDisplayList++, OS_PHYSICAL_TO_K0(D_800E290C), D_80127C04, 1); i += D_80127C00; } - mtx = (u32) &D_800E2904[i]; - gSPVertexDKR(gCurrWeatherDisplayList++, OS_PHYSICAL_TO_K0(mtx), (D_800E2908 - i), 0); + vtx = (u32) &D_800E2904[i]; + gSPVertexDKR(gCurrWeatherDisplayList++, OS_PHYSICAL_TO_K0(vtx), (D_800E2908 - i), 0); gSPPolygon(gCurrWeatherDisplayList++, OS_PHYSICAL_TO_K0(D_800E290C), ((s32) (D_800E2908 - i) >> 1), 1); } } } -UNUSED void func_800AC850(void) { - D_800E2A84 = TRUE; +/** + * Disable lens flare rendering. + */ +UNUSED void lensflare_off(void) { + gLensFlareOff = TRUE; } -UNUSED void func_800AC860(void) { - if (D_800E2A80 != NULL) { - D_800E2A84 = FALSE; +/** + * Enable lens flare rendering, if possible. + */ +UNUSED void lensflare_on(void) { + if (gLensFlare != NULL) { + gLensFlareOff = FALSE; } } -void func_800AC880(Object *obj) { - if (obj == D_800E2A80) { - D_800E2A80 = NULL; - D_800E2A84 = TRUE; +/** + * Removes the lens flare object from the weather system, + * meaning it won't be seen anymore. Also disables lens flare rendering. + */ +void lensflare_remove(Object *obj) { + if (obj == gLensFlare) { + gLensFlare = NULL; + gLensFlareOff = TRUE; } } -void func_800AC8A8(Object *lensflareObj) { +/** + * Sets the weather systems' lens flare object to this. + * Afterwards, assigns presets based on the spawn parameters. + * Finally, set the screenspace matrix position. + */ +void lensflare_init(Object *obj) { LevelObjectEntry_LensFlare *entry; - Vec3s sp1C; + Vec3s angle; - D_800E2A80 = lensflareObj; - D_800E2A84 = 0; - entry = &D_800E2A80->segment.level_entry->lensFlare; + gLensFlare = obj; + gLensFlareOff = FALSE; + entry = &gLensFlare->segment.level_entry->lensFlare; - switch (entry->unkC) { + switch (entry->set1) { default: - D_80127C24 = 0; + gLensFlareSet1 = NULL; break; case 1: - D_80127C24 = (s32) D_800E29A0; + gLensFlareSet1 = gLensPreset1; break; case 2: - D_80127C24 = (s32) D_800E29E0; + gLensFlareSet1 = gLensPreset2; break; case 3: - D_80127C24 = (s32) D_800E2A30; + gLensFlareSet1 = gLensPreset3; break; } - switch (entry->unkD) { + switch (entry->set2) { default: - D_80127C28 = 0; + gLensFlareSet2 = NULL; break; case 1: - D_80127C28 = (s32) D_800E29A0; + gLensFlareSet2 = gLensPreset1; break; case 2: - D_80127C28 = (s32) D_800E29E0; + gLensFlareSet2 = gLensPreset2; break; case 3: - D_80127C28 = (s32) D_800E2A30; + gLensFlareSet2 = gLensPreset3; break; } - if (entry->unkE == 1) { - D_80127C2C = (Matrix *) D_800E2980; + if (entry->largeShine == 1) { + gLensFlareLarge = gLensPresetLarge; } else { - D_80127C2C = NULL; + gLensFlareLarge = NULL; } - sp1C.y_rotation = entry->unkA; - sp1C.x_rotation = entry->unk8; - sp1C.z_rotation = 0; - D_80127C30.x = 0; - D_80127C30.y = 0; - D_80127C30.z = -1.0f; - f32_vec3_apply_object_rotation3((ObjectTransform *) &sp1C, D_80127C30.f); - D_80127C30.x = -D_80127C30.x; - D_80127C30.y = -D_80127C30.y; - D_80127C30.z = -D_80127C30.z; + angle.y_rotation = entry->angleY; + angle.x_rotation = entry->angleX; + angle.z_rotation = 0; + gLensFlarePos.x = 0; + gLensFlarePos.y = 0; + gLensFlarePos.z = -1.0f; + f32_vec3_apply_object_rotation3((ObjectTransform *) &angle, gLensFlarePos.f); + gLensFlarePos.x = -gLensFlarePos.x; + gLensFlarePos.y = -gLensFlarePos.y; + gLensFlarePos.z = -gLensFlarePos.z; } // https://decomp.me/scratch/mYuMJ +// lensflare_render GLOBAL_ASM("asm/non_matchings/weather/func_800ACA20.s") -void cameraAddOverrideObject(Object *arg0) { - if (D_800E2A88 < 0x10) { - D_80127C40[D_800E2A88] = arg0; - D_800E2A88++; +/** + * Adds the new override object to the end of the list, + * so the game can use it for applying overrides. + */ +void lensflare_override_add(Object *obj) { + if (gLensFlareOverrideObjs < WEATHER_OVERRIDE_COUNT) { + gLensFlareSwitches[gLensFlareOverrideObjs] = obj; + gLensFlareOverrideObjs++; + } else { + stubbed_printf("\nMaximum limit of %d lens flare switches, per level, has been exceeded.", + WEATHER_OVERRIDE_COUNT); } } -void func_800ACF98(Object *arg0) { +/** + * Check if the lens flare switch object is registered. + * If so, remove it from the list, then move any further objects forward to fill the gap. + */ +void lensflare_override_remove(Object *obj) { s32 i; s32 isFound = FALSE; - for (i = 0; i < D_800E2A88 && !isFound; i++) { - if (D_80127C40[i] == arg0) { + for (i = 0; i < gLensFlareOverrideObjs && !isFound; i++) { + if (gLensFlareSwitches[i] == obj) { isFound = TRUE; } } if (isFound) { - D_800E2A88--; + gLensFlareOverrideObjs--; i--; - for (; i < D_800E2A88; i++) { - D_80127C40[i] = D_80127C40[i + 1]; + for (; i < gLensFlareOverrideObjs; i++) { + gLensFlareSwitches[i] = gLensFlareSwitches[i + 1]; } } } -void func_800AD030(ObjectSegment *cameraSegment) { - LevelObjectEntry_Weather *weather; +/** + * Check if the camera is inside the radius of a lens flare override. + * If so, disable the lens flare effect while it remains inside. + */ +void lensflare_override(ObjectSegment *cameraSegment) { + LevelObjectEntry_LensFlareSwitch *lensFlare; f32 xDiff; f32 zDiff; f32 yDiff; s32 i; - D_800E2A84 = FALSE; - if (D_800E2A88 > 0 && D_800E2A80 != 0) { - if (D_80127C40[0]) {} // Fakematch - for (i = 0; i < D_800E2A88; i++) { - xDiff = cameraSegment->trans.x_position - D_80127C40[i]->segment.trans.x_position; - yDiff = cameraSegment->trans.y_position - D_80127C40[i]->segment.trans.y_position; - zDiff = cameraSegment->trans.z_position - D_80127C40[i]->segment.trans.z_position; - weather = &D_80127C40[i]->segment.level_entry->weather; - if (sqrtf((xDiff * xDiff) + (yDiff * yDiff) + (zDiff * zDiff)) < weather->radius) { - D_800E2A84 = TRUE; + + gLensFlareOff = FALSE; + if (gLensFlareOverrideObjs > 0 && gLensFlare != 0) { + if (gLensFlareSwitches[0]) {} // Fakematch + for (i = 0; i < gLensFlareOverrideObjs; i++) { + xDiff = cameraSegment->trans.x_position - gLensFlareSwitches[i]->segment.trans.x_position; + yDiff = cameraSegment->trans.y_position - gLensFlareSwitches[i]->segment.trans.y_position; + zDiff = cameraSegment->trans.z_position - gLensFlareSwitches[i]->segment.trans.z_position; + lensFlare = &gLensFlareSwitches[i]->segment.level_entry->lensFlareSwitch; + if (sqrtf((xDiff * xDiff) + (yDiff * yDiff) + (zDiff * zDiff)) < lensFlare->radius) { + gLensFlareOff = TRUE; } } } diff --git a/src/weather.h b/src/weather.h index a1c9d745..9a0ddaaa 100644 --- a/src/weather.h +++ b/src/weather.h @@ -34,13 +34,12 @@ typedef struct unk800E2850 { } unk800E2850; /* Size: 0x10 Bytes */ -typedef struct unk800E2980 { - s32 unk0; - u16 unk4; - u16 unk6; - f32 unk8; - f32 unkC; -} unk800E2980; +typedef struct LensFlareData { + s32 count; // Amount of pieces to draw + ColourRGBA colour; + f32 scale; + f32 offset; +} LensFlareData; /* Size: 0x1C Bytes */ typedef struct unk800E2B4C { @@ -90,8 +89,8 @@ typedef struct unk800E28D4 { } unk800E28D4; void set_weather_limits(s16 arg0, s16 arg1); -void func_800AC880(Object *obj); -void cameraAddOverrideObject(Object *arg0); +void lensflare_remove(Object *obj); +void lensflare_override_add(Object *obj); void free_rain_memory(void); void func_800AD2C4(s32 arg0, s32 arg1, f32 arg2); void func_800AD40C(void); @@ -104,7 +103,7 @@ void process_weather(Gfx **currDisplayList, MatrixS **currHudMat, Vertex **currH void render_falling_snow(void); void free_weather_memory(void); void changeWeather(s32 arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5); -void func_800AD030(ObjectSegment *cameraSegment); +void lensflare_override(ObjectSegment *cameraSegment); void func_800AC0C8(s32 updateRate); s32 coss(s16); @@ -112,7 +111,7 @@ s32 sins(s16); void init_weather(void); void f32_matrix_dot(Matrix *arg0, Matrix *arg1, Matrix *arg2); void func_800AC21C(void); -void func_800AC8A8(Object *); +void lensflare_init(Object *); void func_800ACA20(Gfx**, MatrixS**, Vertex**, ObjectSegment*); void func_800AB4A8(s32 weatherType, s32 weatherEnable, s32 velX, s32 velY, s32 velZ, s32 intensity, s32 opacity);